|
2 | 2 | * [基础概念](#基础概念) |
3 | 3 | * [进程与线程](#进程与线程) |
4 | 4 | * [单线程与多线程](#单线程与多线程) |
5 | | - * [实现线程的4中方式](#实现线程的4中方式) |
6 | | - * [thread.start()和runnable.run()的区别](#thread.start()和runnable.run()的区别) |
7 | | - * [Thread和Runnable的异同](#Thread和Runnable的异同) |
8 | | - * [线程的基本操作](#线程的基本操作) |
9 | | - * [线程的优先级与守护线程](#线程的优先级与守护线程) |
10 | | - * [线程的状态与转换](#线程的状态与转换) |
11 | | - * [synchronized关键字](#synchronized关键字) |
12 | | - * [实例锁与全局锁](#实例锁与全局锁) |
13 | | - * [wait和notify](#wait和notify) |
14 | | - |
15 | | -## 基础概念 |
16 | | - |
17 | | -### 进程与线程 |
| 5 | +* [实现线程的4中方式](#实现线程的4中方式) |
| 6 | + * [thread.start()和runnable.run()的区别](#thread.start()和runnable.run()的区别) |
| 7 | + * [Thread和Runnable的异同](#Thread和Runnable的异同) |
| 8 | +* [线程的基本操作](#线程的基本操作) |
| 9 | +* [线程的优先级与守护线程](#线程的优先级与守护线程) |
| 10 | +* [synchronized关键字](#synchronized关键字) |
| 11 | +* [实例锁与全局锁](#实例锁与全局锁) |
| 12 | +* [wait和notify](#wait和notify) |
| 13 | +* [线程的让步yeild](#线程的让步yeild) |
| 14 | +* [线程的休眠sleep](#线程的休眠sleep) |
| 15 | +* [Thread中的join](#Thread中的join) |
| 16 | +* [线程的中断interrupt](线程的中断interrupt) |
| 17 | +* [线程的状态与转换](#线程的状态与转换) |
| 18 | +* [生产者消费者问题](#生产者消费者问题) |
| 19 | + |
| 20 | +### 基础概念 |
| 21 | + |
| 22 | +#### 进程与线程 |
18 | 23 | `进程(Process)`是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。 在当代面向线程设计的计算机结构中,进程是线程的容器。程序是指令、数据及其组织形式的描述,进程是程序的实体。是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。程序是指令、数据及其组织形式的描述,进程是程序的实体。进程之间通过TCP/IP的端口来实现相互交互。 |
19 | 24 |
|
20 | 25 | `线程(thread)`是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务,多个线程共享本进程的资源。线程的通信就比较简单,有一大块共享的内存,只要大家的指针是同一个就可以看到各自的内存。 |
|
27 | 32 |
|
28 | 33 | `并发`: 对于单核cpu来说,多线程并不是同时进行的,操作系统将时间分成了多个时间片,大概均匀的分配给线程,到达某个线程的时间段,该线程运行,其余时间待命,这样从微观上看,一个线程是走走停停的,宏观感官上,在某一时刻似乎所有线程都在运行。并发是针对时间片段来说的,在某个时间段内多个线程处于runnable到running之间,但每个时刻只有一个线程在running,这叫做并发。 |
29 | 34 |
|
30 | | -### 单线程与多线程 |
| 35 | +#### 单线程与多线程 |
31 | 36 | 单线程就是进程中只有一个线程。单线程在程序执行时,所走的程序路径按照连续顺序排下来,前面的必须处理好,后面的才会执行。 |
32 | 37 | ```java |
33 | 38 | // 单线程实例 |
@@ -151,19 +156,6 @@ public class NewThreadExecutorService { |
151 | 156 | #### thread.start()和runnable.run()的区别 |
152 | 157 | Thread类继承了Runnable接口,调用start()方法会启动一个新的线程来执行相应的run()方法;run()方法和普通的成员方法一样,可以被重复调用,会在当前线程中执行该方法,而不会启动新的线程。(参考上面通过实现Runnable接口来实现新线程) |
153 | 158 |
|
154 | | -### 线程的状态与转换 |
155 | | -线程共包括以下5种状态。 |
156 | | -1. 新建状态(New): 创建了线程对象但尚未调用start()方法时的状态。 |
157 | | -2. 就绪状态(Runnable): 也被称为“可执行状态”。线程对象被创建后,其它线程调用了该对象的start()方法,从而来启动该线程。例如,thread.start()。处于就绪状态的线程,随时可能被CPU调度执行。 |
158 | | -3. 阻塞状态(Blocked): 阻塞状态是线程因为某种原因放弃CPU使用权,暂时停止运行。直到线程进入就绪状态,才有机会转到运行状态。阻塞的情况分三种: |
159 | | - (01) 等待阻塞 -- 通过调用线程的wait()方法,让线程等待某工作的完成。 |
160 | | - (02) 同步阻塞 -- 线程在获取synchronized同步锁失败(因为锁被其它线程所占用),它会进入同步阻塞状态。 |
161 | | - (03) 其他阻塞 -- 通过调用线程的sleep()或join()或发出了I/O请求时,线程会进入到阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。 |
162 | | -4. 等待状态(Waiting):线程处于等待状态,处于该状态标识的当前线程需要等待其他线程做出一些特定的操作来唤醒自己。 |
163 | | -5. 超时等待状态(Time Waiting):超时等待状态,与Waiting不同,在等待指定的时间后会自行返回。 |
164 | | -6. 终止状态(Terminated): 线程执行完了或者因异常退出了run()方法,该线程结束生命周期。 |
165 | | - |
166 | | - |
167 | 159 | ### 线程的优先级与守护线程 |
168 | 160 | > 线程的优先级 |
169 | 161 | Java中的线程优先级的范围是1~10,默认的优先级是5,10极最高。线程的优先级具有以下特性: |
@@ -593,8 +585,61 @@ public void run() { |
593 | 585 | 说明:在while(true)中不断的执行任务,当线程处于阻塞状态时,调用线程的interrupt()产生InterruptedException中断。中断的捕获在while(true)之外,这样就退出了while(true)循环! |
594 | 586 | InterruptedException异常的捕获在whle(true)之内。当产生InterruptedException异常时,被catch处理之外,仍然在while(true)循环体内;要退出while(true)循环体,需要额外的执行退出while(true)的操作。thread在“等待(阻塞)状态”时,被interrupt()中断;此时,会清除中断标记(即isInterrupted()会返回false),而且会抛出InterruptedException异常(该异常在while循环体内被捕获) |
595 | 587 |
|
| 588 | +### 线程的状态与转换 |
| 589 | +线程共包括以下5种状态。 |
| 590 | +1. 新建状态(New): 创建了线程对象但尚未调用start()方法时的状态。 |
| 591 | +2. 就绪状态(Runnable): 也被称为“可执行状态”。线程对象被创建后,其它线程调用了该对象的start()方法,从而来启动该线程。例如,thread.start()。处于就绪状态的线程,随时可能被CPU调度执行。 |
| 592 | +3. 阻塞状态(Blocked): 阻塞状态是线程因为某种原因放弃CPU使用权,暂时停止运行。直到线程进入就绪状态,才有机会转到运行状态。阻塞的情况分三种: |
| 593 | + (01) 等待阻塞 -- 通过调用线程的wait()方法,让线程等待某工作的完成。 |
| 594 | + (02) 同步阻塞 -- 线程在获取synchronized同步锁失败(因为锁被其它线程所占用),它会进入同步阻塞状态。 |
| 595 | + (03) 其他阻塞 -- 通过调用线程的sleep()或join()或发出了I/O请求时,线程会进入到阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。 |
| 596 | +4. 等待状态(Waiting):线程处于等待状态,处于该状态标识的当前线程需要等待其他线程做出一些特定的操作来唤醒自己。 |
| 597 | +5. 超时等待状态(Time Waiting):超时等待状态,与Waiting不同,在等待指定的时间后会自行返回。 |
| 598 | +6. 终止状态(Terminated): 线程执行完了或者因异常退出了run()方法,该线程结束生命周期。 |
| 599 | + |
| 600 | + |
| 601 | +> 补充说明 |
| 602 | +* Thread.sleep(long millis),一定是当前线程调用此方法,当前线程进入TIMED_WAITING状态,但不释放对象锁,millis后线程自动苏醒进入就绪状态。作用:给其它线程执行机会的最佳方式。 |
| 603 | +* Thread.yield(),一定是当前线程调用此方法,当前线程放弃获取的CPU时间片,但不释放锁资源,由运行状态变为就绪状态,让OS再次选择线程。作用:让相同优先级的线程轮流执行,但并不保证一定会轮流执行。实际中无法保证yield()达到让步目的,因为让步的线程还有可能被线程调度程序再次选中。Thread.yield()不会导致阻塞。该方法与sleep()类似,只是不能由用户指定暂停多长时间。 |
| 604 | +* t.join()/t.join(long millis),当前线程里调用其它线程t的join方法,当前线程进入WAITING/TIMED_WAITING状态,当前线程不会释放已经持有的对象锁。线程t执行完毕或者millis时间到,当前线程进入就绪状态。 |
| 605 | +* obj.wait(),当前线程调用对象的wait()方法,当前线程释放对象锁,进入等待队列。依靠notify()/notifyAll()唤醒或者wait(long timeout) timeout时间到自动唤醒。 |
| 606 | +* obj.notify()唤醒在此对象监视器上等待的单个线程,选择是任意性的。notifyAll()唤醒在此对象监视器上等待的所有线程。 |
| 607 | + |
596 | 608 | ### 生产者消费者问题 |
597 | 609 | 所谓的生产者消费者模型,是通过一个容器来解决生产者和消费者的强耦合问题。通俗的讲,就是生产者在不断的生产,消费者也在不断的消费,可是消费者消费的产品是生产者生产的,这就必然存在一个中间容器,我们可以把这个容器想象成是一个货架,当货架空的时候,生产者要生产产品,此时消费者在等待生产者往货架上生产产品,而当货架满的时候,消费者可以从货架上拿走商品,生产者此时等待货架的空位,这样不断的循环。那么在这个过程中,生产者和消费者是不直接接触的,所谓的‘货架’其实就是一个阻塞队列,生产者生产的产品不直接给消费者消费,而是仍给阻塞队列,这个阻塞队列就是来解决生产者消费者的强耦合的。就是生产者消费者模型。 |
| 610 | +```java |
| 611 | +public class Product { |
| 612 | + |
| 613 | + private int size; |
| 614 | + private final int capactiy = 100; |
| 615 | + |
| 616 | + public synchronized void product(int n) { |
| 617 | + while(size >= capactiy) { |
| 618 | + try { |
| 619 | + wait(); |
| 620 | + } catch (InterruptedException e) { |
| 621 | + e.printStackTrace(); |
| 622 | + } |
| 623 | + } |
| 624 | + size+=n; |
| 625 | + System.out.println(Thread.currentThread().getName() + "生产" + n + "个,剩余" + size); |
| 626 | + notifyAll(); |
| 627 | + } |
| 628 | + |
| 629 | + public synchronized void consume(int n) { |
| 630 | + while ((size - n) < 0) { |
| 631 | + try { |
| 632 | + wait(); |
| 633 | + } catch (InterruptedException e) { |
| 634 | + e.printStackTrace(); |
| 635 | + } |
| 636 | + } |
| 637 | + size-=n; |
| 638 | + System.out.println(Thread.currentThread().getName() + "消费" + n + "个,剩余" + size); |
| 639 | + notifyAll(); |
| 640 | + } |
| 641 | +} |
| 642 | +``` |
598 | 643 |
|
599 | 644 | # 引用 |
600 | 645 | * https://www.cnblogs.com/skywang12345/ |
|
0 commit comments