From 147ca43b3cb5664fd2dcbabc8e4cfb8766ce61c2 Mon Sep 17 00:00:00 2001 From: tangxuan Date: Fri, 15 May 2020 00:43:23 +0800 Subject: [PATCH 1/2] =?UTF-8?q?leetcode:4.=E5=AF=BB=E6=89=BE=E4=B8=A4?= =?UTF-8?q?=E4=B8=AA=E6=AD=A3=E5=BA=8F=E6=95=B0=E7=BB=84=E7=9A=84=E4=B8=AD?= =?UTF-8?q?=E4=BD=8D=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...04\344\270\255\344\275\215\346\225\260.md" | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 "TangXuan/leetcode/4.\345\257\273\346\211\276\344\270\244\344\270\252\346\255\243\345\272\217\346\225\260\347\273\204\347\232\204\344\270\255\344\275\215\346\225\260.md" diff --git "a/TangXuan/leetcode/4.\345\257\273\346\211\276\344\270\244\344\270\252\346\255\243\345\272\217\346\225\260\347\273\204\347\232\204\344\270\255\344\275\215\346\225\260.md" "b/TangXuan/leetcode/4.\345\257\273\346\211\276\344\270\244\344\270\252\346\255\243\345\272\217\346\225\260\347\273\204\347\232\204\344\270\255\344\275\215\346\225\260.md" new file mode 100644 index 0000000..2f4ff30 --- /dev/null +++ "b/TangXuan/leetcode/4.\345\257\273\346\211\276\344\270\244\344\270\252\346\255\243\345\272\217\346\225\260\347\273\204\347\232\204\344\270\255\344\275\215\346\225\260.md" @@ -0,0 +1,43 @@ +# 4.寻找两个正序数组的中位数 + +要求时间复杂度为O(log(n+m)) + +```java +class Solution { + public double findMedianSortedArrays(int[] A, int[] B) { + int m = A.length; + int n = B.length; + if (m > n) { // to ensure m<=n + int[] temp = A; A = B; B = temp; + int tmp = m; m = n; n = tmp; + } + int iMin = 0, iMax = m, halfLen = (m + n + 1) / 2; + while (iMin <= iMax) { + int i = (iMin + iMax) / 2; + int j = halfLen - i; + if (i < iMax && B[j-1] > A[i]){ + iMin = i + 1; // i is too small + } + else if (i > iMin && A[i-1] > B[j]) { + iMax = i - 1; // i is too big + } + else { // i is perfect + int maxLeft = 0; + if (i == 0) { maxLeft = B[j-1]; } + else if (j == 0) { maxLeft = A[i-1]; } + else { maxLeft = Math.max(A[i-1], B[j-1]); } + if ( (m + n) % 2 == 1 ) { return maxLeft; } + + int minRight = 0; + if (i == m) { minRight = B[j]; } + else if (j == n) { minRight = A[i]; } + else { minRight = Math.min(B[j], A[i]); } + + return (maxLeft + minRight) / 2.0; + } + } + return 0.0; + } +} +``` + From f32a3f38e288372092015d6a32a1902596bfaa3a Mon Sep 17 00:00:00 2001 From: tangxuan Date: Sun, 17 May 2020 00:13:45 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E3=80=8AJava=E5=B9=B6=E5=8F=91=E7=BC=96?= =?UTF-8?q?=E7=A8=8B=E4=B9=8B=E7=BE=8E=E3=80=8B=EF=BC=9A=E7=AC=AC=E4=B8=80?= =?UTF-8?q?=E7=AB=A0=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...77\347\250\213\345\237\272\347\241\200.md" | 162 ++++++++++++++++++ 1 file changed, 162 insertions(+) create mode 100644 "TangXuan/\343\200\212The beauty of concurrent programming\343\200\213/\345\271\266\345\217\221\347\274\226\347\250\213\347\272\277\347\250\213\345\237\272\347\241\200.md" diff --git "a/TangXuan/\343\200\212The beauty of concurrent programming\343\200\213/\345\271\266\345\217\221\347\274\226\347\250\213\347\272\277\347\250\213\345\237\272\347\241\200.md" "b/TangXuan/\343\200\212The beauty of concurrent programming\343\200\213/\345\271\266\345\217\221\347\274\226\347\250\213\347\272\277\347\250\213\345\237\272\347\241\200.md" new file mode 100644 index 0000000..9362159 --- /dev/null +++ "b/TangXuan/\343\200\212The beauty of concurrent programming\343\200\213/\345\271\266\345\217\221\347\274\226\347\250\213\347\272\277\347\250\213\345\237\272\347\241\200.md" @@ -0,0 +1,162 @@ +# 并发编程线程基础 + +## 1.1 线程 + +**进程:** + +* 代码在数据集合上的一次运行活动; +* 系统进行资源分配和调度的基本单位。 + +**线程:** + +* 进程的一个执行路径; +* 进程运行的基本单位,操作系统能够调度的最小单位; + +> 一个进程中至少有一个线程; +> +> 一个进程中的多个线程共享进程的堆和方法栈; +> +> 每个线程拥有自己的程序计数器(记录当前要执行的指令地址)和栈区(存储该线程局部变量,以及调用栈帧) +> +> 进程的堆存放new操作创建的对象实例; +> +> 进程的方法区存放JVM加载的类、常量、静态变量; + +*** + +## 1.2 线程创建与运行 + +**三种创建方法:** + +1. 继承Thread类重写run() +2. 实现Runnable接口的run() +3. 使用FutureTask方式 + +**区别:** + +1. 继承Thread类代码和任务没有分离,多个线程要执行相同代码需要多分任务代码; +2. 继承Thread类代码只能单继承,不能再继承其他类; +3. 继承Thread类和实现Runnable接口均无返回值,FutureTask方式拥有返回值; + +*** + +## 1.3 线程通知和等待 + +#### 1> wait()函数 + +**作用:** 当一个线程调用一个共享变量的wait()方法时,该线程进入阻塞状态; + +**阻塞态返回条件:** + +* 其他线程调用了该共享对象的notify()或者notifyAll()方法; +* 其他线程调用了该线程的interrupt()方法,该线程抛出 InterruptException异常返回。 + +> 若调用wait()方法的线程没有事先获取该对象的监视器锁,则会抛出IllegealMonitorStateException异常 + +**如何获取共享变量的监视器锁:** + +* 执行synchronized同步代码块时,使用该共享变量作为参数 + +``` +synchronized(共享变量){ do something;} +``` + +* 调用该共享变量的方法,该方法使用synchronized修饰。 + +**注意:虚假唤醒** + +> 一个线程可以从挂起状态转变为可运行态(被唤醒),即使该线程没有被唤醒、中断、等待超时。 + +*** + +#### 2> notify()函数 + +**作用:** 一个线程调用共享对象的notify()后,会随机唤醒一个在公共变量上调用wait系列方法后被挂起的线程。 + +> 被唤醒的线程并不能马上从wait()方法返回并执行,必须获取共享独享的监视器锁后才可以返回,也就是说竞争到锁后才执行。 + +*** + +### 1.4 join()函数 + +**作用:** + +``` +thread.Join()把指定的线程加入到当前线程,可以将两个交替执行的线程合并为顺序执行的线程。比如在线程B中调用了线程A的Join()方法,直到线程A执行完毕后,才会继续执行线程B。 +``` + +*** + +### 1.5 sleep()函数 + +**定义:** + +* Thread类中的静态方法; +* 执行中的线程调用该方法后,该线程会暂时让出指定时间的执行权,不参与cpu调度; +* 不让出该线程拥有的监视器资源,比如锁; +* 睡眠期间其他线程调用了该线程的interrupt()方法,则会再sleep()方法的地方抛出InterruptException异常。 + +*** + +### 1.6 让出CPU执行权的 yield()方法 + +**定义:** + +* Thread类中的静态方法; +* 线程再调用yield()方法时,就是在暗示线程调度器,当前线程让出自己的cpu使用权; +* 暗示可以开始下一轮调度; +* 但是线程调度器可以无条件忽略这个请求。 + +*** + +### 1.7 线程中断 + +**定义:** + +* 一种线程间的协作模式; +* 但是,设置线程中断状态并不能直接终止该线程的执行,而是由其根据中断状态自行处理; + +**方法:** + +* void interrupt() : 中断线程,设置中断标志为 true()立马返回,仅仅是设置状态,线程并没有中断,会继续执行。 +* boolean isInterrupted():检测当前线程是否被中断,如果是,返回true;如果否,返回false。**不会清除中断标志**。 +* boolean interrupted():作用同上; + * 但不同之处,如果发现当前线程被中断,会清楚中断标志; + * static方法,可直接调用; + * **获取到的是当前线程的中断标志,不是调用该方法的实例对象的标志**。 + +**** + +### 1.8 线程上下文切换 + +* 线程个数 > CPU 个数 (一般情况); +* 线程调度方式为:**CPU时间片轮询**; +* **上下文切换:** 当前线程使用完时间皮后,就会处于就绪状态并让出CPU执行权给其他线程使用。 +* 保存当前线程执行现场。 + +**** + +### 1.9 线程死锁 + +#### 定义 + +**两个或两个以上的线程再执行过程中,因争夺资源而造成的互相等待的现象。** + +**条件** + +* **互斥条件:** 线程对已获取到的资源具有排他性,其他线程只能等待; +* **请求并持有条件:** 一个线程至少持有一个资源,但又请求其他资源; +* **不可剥夺条件:** 线程获取到的资源在自己使用完之前,其他线程不能占用; +* **环路等待条件:** 在发生死锁时,必然存在一个线程 —— 资源的环形链。 + +**如何避免** + +**目前只能破坏:** + +* 请求并持有条件; +* 环路等待条件。 + +**使用资源时遵循申请的有序性原则。** + + +