从0开始学Java并发(一)——基本概念

什么是多线程

进程:Process,系统级别的资源调度单位。相当于一个程序实例

线程:Thread,进程内的资源调度单位,在进程内运行的最小单位,有自己的计数器和内存堆栈结构。

多线程的好处

  1. 多核处理器资源利用更加充分
  2. 使程序响应时间更快
  3. 构建更好的编程模型

一个线程的生命周期

下图一共7个状态,创建预备运行定时等待等待阻塞终止
而其他书上有简略版的,如:

这些生命周期的状态在Java里就是对应线程的六个状态

摘自《Java并发编程的艺术》

线程从创建到结束

1. 线程的创建

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// 直接new,或者创建Thread的子类(我用匿名方式替代了一下)
Thread t = new Thread(){
@Override
public void run() {
super.run();
}
};
t.start();

// 用 Runnable (我用lambda替代了一下)
Thread t = new Thread(() -> System.out.println("new t"));
t.start();

// 用Timmer(其实是定时任务,在另一个线程中)
Timer t = new Timer();
t.schedule(new TimerTask() {
@Override
public void run() {
System.out.println(Instant.now());
}
}, 1000, 1000);


// Future来包装Callable
ThreadPoolExecutor executorService = new ThreadPoolExecutor(1, 1, 1L, TimeUnit.MINUTES,
new ArrayBlockingQueue<Runnable>(1), new ThreadPoolExecutor.DiscardPolicy());
System.out.println(Thread.currentThread().getName());
try {
Future t = executorService.submit(() -> Thread.currentThread().getName());
System.out.println(t.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}

还有线程池,上面Future就是使用线程池的,线程池一般很少创建单线程的,除非业务需要,所以下回再说,写个demo

1
2
ExecutorService executor = Executors.newSingleThreadExecutor();
executor.execute(() -> System.out.println(Thread.currentThread().getName()));

最为传统的方法就是new Thread,但是这种用法在大型软件开发中几乎不用,而是根据线程模型选择Future或者线程池去执行异步任务。这里的例子仅为展示线程的创建方法

2. 线程的终止

当线程逻辑运行完成后会自动退出。
但是如果线程执行过程中,某些条件不满足,导致线程等待或者阻塞,就可能会导致异常终止。

suspendresumestop被废弃了,原因是可能造成死锁,数据异常等问题。想要安全退出线程,可以使用中断请求标记来检查线程状态,检查到中断信号后,处理完数据、释放锁,再退出线程即可。

3. 中断

当线程的interrupt方法被其他线程调用的时候,这个线程就会接收到中断请求,如果线程自己检查isInterruted检查中断状态,也可以使用Thread.interrupted()静态方法恢复中断状态。
许多抛InterruptedException的方法就是接受到中断请求,一般情况下会清除该线程中断标记,再抛出异常。

线程的类别、属性等参数(优先级,状态)

创建预备运行定时等待等待阻塞终止。其中预备和运行都被Java定义为RUNABLE状态

线程的生命周期

状态名称 说明
NEW 初始状态,线程被构建,但是还没有调用 start() 方法
RUNABLE 运行状态,Java线程将操作系统中的就绪和运行两种状态笼统地称作“运行中”
BLOCKED 阻塞状态,表示线程阻塞于锁
WAITING 等待状态,表示线程进入等待状态,进入该状态表示当前线程需要等待其他线程做出一些特定动作(通知或中断)
TIME_WAITING 超时等待状态,不同于WAITING,它是可以在指定时间内自行返回的
TERMINATED 终止状态,表示当前线程已经执行完毕

线程分类方式有很多种,除了前面创建方式分类其实还有一种分类方式

Daemon线程和非Daemon线程(守护线程,非守护线程)
Thread直接new的线程可以直接调用setDaemon (true)将这个线程设为守护线程。设置为守护线程后线程将会随虚拟机一直在幕后工作,前台是基本观察不到的。除非手动关闭,否则直到JVM准备关闭时,这个线程才会随之一同终止。

喜欢请点个赞,
转载请注明出处:https://www.jianshu.com/u/4915ed24d1e3
如有错误,请务必指正!谢谢!
我的博客:https://xzing.github.io/