
多线程基础(一)
2020-12-19 / highPhone啊
线程简介
进程:应用程序的执行实例,有独立内存空间和系统资源
线程:cpu调度和分派的基本单位,进程中执行运算最小的单位,可完成一个独立顺序控制流程
多线程:
在一个进程中同时运行了多个线程,完成不同的工作
多个线程交替占用cpu资源,而非真正并行执行
好处:
充分利用cpu资源
简化编程模型
带来良好用户体验创建线程的三种方式
继承Thread类
1. 编写自己的线程类,使用extends关键字继承Thread类
2. 重写继承自Thread类的run方法,自定义自己的线程工作内容
3. 创建自定义线程对象,调用start()方法启动线程
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class ThreadTest1 extends Thread{
public static void main(String[] args) {
ThreadTest1 thread1 = new ThreadTest1("线程一");
ThreadTest1 thread2 = new ThreadTest1("线程二");
thread1.start();
thread2.start();
}
public ThreadTest1(String name) {
super(name);
}
public void run() {//线程每秒打印i,从1到10
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName() + "正在打印:" + i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}

实现Runnable接口
1. 编写自己的线程类,使用implements关键字实现Runnable接口
2. 重写Runnable接口的run方法,自定义线程工作内容
3. 创建自定义线程对象,通过new Thread().start()传入自定线程对象的方式启动自定义线程(静态代理)。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class ThreadTest2 implements Runnable{
public static void main(String[] args) {
ThreadTest2 thread1 = new ThreadTest2();
ThreadTest2 thread2 = new ThreadTest2();
new Thread(thread1, "线程一").start();
new Thread(thread2, "线程二").start();
}
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName() + "正在打印" + i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
Runnable接口其实是一个函数式接口,通过实现Runnable接口方式创建线程,还可以使用Lambda表达式创建自定义线程对象,这样可以让代码更加简洁:
1
2
3
4
5
6
7
8
9
10
11
12
13
14public class ThreadTest3 {
public static void main(String[] args) {
new Thread(()->{
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName() + "正在打印" + i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "线程一").start();
}
}实现Callable接口
编写自定义线程类,使用implements实现Callable
接口 重写Callable接口的call方法,自定义线程工作内容,根据实际情况确定线程方法体的返回值,返回值就是Callable
中的泛型。 创建ExecutorService,通过sumbit()启动线程,submit()返回方法体返回值类型一致的Future
,可以获得线程执行完的返回值。 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
27public class ThreadTest4 implements Callable<Boolean> {
public static void main(String[] args) {
ExecutorService service = Executors.newSingleThreadExecutor();
Future<Boolean> future = service.submit(new ThreadTest4());
try {
Boolean callResult = future.get();
System.out.println("线程执行结果返回是" + callResult);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
finally {
service.shutdown();
}
}
public Boolean call() throws Exception {
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName() + "正在打印" + i);
Thread.sleep(1000);
}
return true;
}
}
虽然是实现 Callable ,但是在 Executor 实际运行时,会将 Runnable 的实例或 Callable 的实例转化为 RunnableFuture 的实例,而 RunnableFuture 继承了 Runnable 和 Future 接口。另外,相比实现Runnable接口,实现Callable接口有以下优点:
- Callable 可以在任务结束的时候提供一个返回值,Runnable 无法提供这个功能
- Callable 的 call 方法分可以抛出异常,而 Runnable 的 run 方法不能抛出异常。
线程状态及Thread常用方法
线程状态

- 新生状态状态(new)
Thread t = new Thread(),线程对象一旦创建就进入到新生状态 - 就绪状态(Runnable)
可执行状态,当调用start()方法启动线程后,线程进入就绪状态,可以被CPU调度执行,但不意味着会立即调度 - 运行状态(Running)
线程被CPU调度,获得CPU资源后进入运行状态,执行run()方法里的线程体代码块。 - 阻塞状态(Blocked)
当调用sleep(),wait()或同步锁定等,线程需要等待唤醒或者需要等待别的线程释放锁定资源时,线程进入阻塞状态,就是代码块不往下执行,等待阻塞时间解除后,重新进入就绪状态,等待CPU调度执行。 - 死亡状态(Dead)
线程发生异常或者被外部中断,或者线程执行完毕正常结束后,线程进入死亡状态。线程一旦进入死亡状态,就不能够再次启动。
Thread常用方法
- setPriority(int newPriority)
更改线程优先级,数字越大,优先级越高,但线程优先级并不是绝对的,有可能存在低优先级的线程比高优先级线程先被CPU调度的情况 - static void sleep(long milllis)
在指定毫秒数内让当前线程休眠,休眠结束后重新进入就绪状态等待CPU调度 - void join()
别的线程等待当前线程终止后再执行(插队) - static void yield()
暂停当前正在执行的线程对象,释放CPU资源,重新进入就绪状态(礼让其他线程),但yield()礼让不一定会成功,只是让当前执行的线程重新回到就绪状态,和其他线程再次竞争CPU资源,也有可能会再次被CPU调度。 - final void stop()
停止当前线程,但是不建议使用,此方法已被声明为废弃 - void destroy()
销毁线程,同stop(),此方法也被废弃要终止一个线程,我们可以通过自定义标志位,并自行声明stop()供外界调用以终止线程
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
30public class ThreadTest2 implements Runnable{
private boolean flag = true;
public static void main(String[] args) {
ThreadTest2 thread1 = new ThreadTest2();
ThreadTest2 thread2 = new ThreadTest2();
new Thread(thread1, "线程一").start();
new Thread(thread2, "线程二").start();
}
public void run() {
while (true)
{
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName() + "正在打印" + i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public void stop()
{
this.flag = false;
}
}
本文链接:https://highphone.xyz/241f90c5.html