Java 核心技术卷1 --第十四章 并发
作者:互联网
Github代码链接: https://github.com/deyou123/corejava.git
第十四章 并发
- 每一个任务称为一个线程;是线程控制的简称;
- 多线程程序:同时运行一个以上线程的程序。
- 每个进程拥有自己的一整套变量;而线程则共享数据;
- 共享变量使线程之间的通信比进程之间的通信更有效、更容易;线程比进程更“轻量级”,线程的创建和撤销开销小。
14.1 什么是线程
14.1.1 使用线程给其他任务提供机会
public interface Runnable
{
void run();
}
Runnable r = ()->{task code};
Thread t = new Thread(r);
t.start();
14.2 中断线程
Runnable r= ()-> {
try
{
while (!Thread.currentThread().islnterrupted0 && morework todo)
{
do more work
}
}
catch(InterruptedException e)
{
// thread was interr叩ted during sleep or wait
}
finally
{
cleanup,ifrequired
}
// exiting the run method terminates the thread
} ;
14.3 线程状态
线程可以有如下6 种状态:
- New (新创建)
- Runnable (可运行)
- Blocked ( 被阻塞)
- Waiting (等待)
- Timed waiting (计时等待)
- Terminated ( 被终止)
14.3.1 新建线程
new Thread®; 线程还没开始运行;
14.3.2 可运行线程
- 一旦调用start方法,线程处于 runnable状态;
- 可能正在运行; 也可能没有运行;
14.3.3 被阻塞线程和等待线程
暂时不活动;不运行任何代码且消耗最小资源;
- 一个线程试图获取一个内部的对象琐,该琐被其他线程所持有,该线程进入阻塞状态;当所有其他线程释放该琐,并且线程调度器允许本线程持有他,该线程变成非阻塞状态;
- 当线程等待另一个线程通知调度器一个条件时,他进入等待状态;
- 有几个方法有一个超时参数。调用他们呆滞线程进入计时等待状态(timed waiting,状态将一直保持到超时期满或者接收到适当的通知。
超时参数的方法有:Thread.sleep、Object.wait、Thread.join、Lock.tryLock和Condition.await;
14.3.4 被终止的线程
两个原因:
- run方法正常退出而自然死亡;
- 因为一个没有捕获的异常终止了run方法而意外死亡;
14.4 线程属性
14.4.1 线程优先级
-
每个线程又有个优先级;
-
默认情况,一个线程继承它父线程的优先级;
-
setPriority方法提高或降低线程的优先级
-
优先级设置为MIN_PRIORITY和MAX_PRIORITY之间的任何值。NORM_PRIORITY被定义为5;
-
线程调度器优先选择较高优先级线程;
-
线程优先级高度依赖于系统;
14.4.2 守护线程
- t.setDaemon(true);
将线程转换为守护线程(daemon thread) - 唯一用途:为其他线程提供服务;
- 计时器,定时发送“计时器滴答”信号给其他线程;或清空过时的高速缓存项的线程;
- 只剩下守护线程时,虚拟机就推出了;
- 守护线程应该永远不去访问固有资源,如文件、数据库等; 它会在任何时候升值在一个操作的中间发生中断;
14.4.3 未捕获异常处理器
- 处理器必须属于一个实现 Thread.UncaughtExceptionHandler接口的类;
void uncaughtException(Thread t, Throwable e); - 可以用setUncaughtExceptionHandler方法为任何线程安装一个处理器;
- 也可以用Thread类的静态方法 setDefaultUncaughtExceptionHandler 为所有线程安装一个默认的处理器;
- 默认的处理器为空;此时的处理器就是该线程的ThreadGroup对象;
uncaughtException方法做如下操作:
1、如果该线程组有父线程组,那么父线程组的uncaughtException方法被调用;
2、否则,如果Thread.getDefaultExceptionHandler方法返回一个非空的处理器,则调用该处理器。
3、否则,如果Throwable是ThreadDeath的一个实例,什么都不做
4、否则,线程的名字以及Throwable的战轨迹被输出到System.err上。
14.5 同步
两个或两个以上的
14.6 阻塞队列
- 多线程问题,可以通过使用一个或多个队列以优雅且安全的方式将其形式化。
生产者线程向队列插入元素,消费者线程取出他们。 - 使用队列,可以安全的从一个线程向另一个线程传递数据。
将指令对象插入队列,另一个线程从队列取出指令执行转账;只有该线程可以访问银行对象的内部,因此不需要同步。
阻塞队列:试图向队列添加元素而队列已满,或是想从队列移除元素而队列为空的时候,导致线程阻塞。
多线程合作:工作者线程可以周期性的将中间结果放在阻塞队列;其他的工作者线程移出中间结果并进一步加以修改。
- 队列会自动地平衡负载,互相等待。
阻塞队列分为3类,取决于当队列满或空时他们的响应方式。
- 当队列当作县城管理工具来使用,用put和take方法。
- 当试图向满地队列中添加或从空的队列中移除元素时,add、remove、element操作抛出异常。
- 一个多线程程序中,队列会在任何时候满或空,一定要用offer、poll、peek方法做替代。
注释
因为poll、peek返回空代表失败,向队列插入null值是非法的。
- 带超时地offer方法和poll方法地变体:
-
boolean success = q.offer(x, 100, TimeUnit.MILLISECONDS);
100毫秒内在队列尾部插入一个元素,成功true;否则超时,false; -
Object head = q.poll(100, TimeUnit.MILLISECONDS);
-
14.7 线程安全的集合
14.7.1 高效地映射、集合队列
java.util.concurrent提供: ConcurrentHashMap、ConcurrentSkipListMap、ConcurrentSkipListSet和ConcurrentLinkedQueue。
14.8 Callable与Future
14.9 执行器
14.10 同步器
14.11 线程与Swing
标签:Java,Thread,--,队列,线程,处理器,第十四章,优先级,方法 来源: https://blog.csdn.net/weixin_44919162/article/details/117669322