多线程(实现方式,常用方法,生命周期)
概述:
- 可以让程序同时做多件事情;
- 可以提高效率;
- 只要你想让多个事情同时运行就需要用到多线程;
- 如: 软件中的耗时操作、所有的聊天软件、所有的服务器‘
并发和并行:
- 并发:在同一时刻,有多个指令在单个CPU上交替执行;
- 并行:在同一时刻,有多个指令在多个CPU上同时执行;
多线程的实现方式:
继承Thread类的方式进行实现:
- 此子类应继承
Thread
类并重写run
方法。 然后可以分配和启动子类的实例; - 然后再创建该对象,调用start方法,则可以启动这个线程,会自动调用run方法;
package com.caihongjia.a0threadcase1;
public class ThreadDemo {
public static void main(String[] args) {
MyThread t1 = new MyThread();
MyThread t2 = new MyThread();
t1.setName("线程一");
t2.setName("线程二");
t1.start();
t2.start();
}
}
package com.caihongjia.a0threadcase1;
public class MyThread extends Thread{
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(getName() + "666");
}
}
}
实现Runnable接口的方式进行实现:
- 此子类应继承
Runnable
类并重写run
方法; - 创建一个实例,然后在创建
Thread
时作为参数传递,调用start方法,则可以启动这个线程;
package com.caihongjia.a0threadcase2;
public class ThreadDemo {
public static void main(String[] args) {
//创建MyRun的对象
//表示多线程要执行的任务
MyRun mr = new MyRun();
//创建线程对象
Thread t1 = new Thread(mr);
Thread t2 = new Thread(mr);
//给线程设置名字
t1.setName("线程1");
t2.setName("线程2");
//开启线程
t1.start();
t2.start();
}
}
package com.caihongjia.a0threadcase2;
public class MyRun implements Runnable{
@Override
public void run() {
//书写线程要执行的代码
for (int i = 0; i < 100; i++) {
//获取到当前线程的对象
Thread t = Thread.currentThread();
System.out.println(t.getName() + "666");
}
}
}
利用Callable接口和Future接口方式实现:
- 特点:可以获得到多线程运行的结果;
- 创建一个类MyCallable实现Callable接口;
- 重写call(是有返回值的,表示多线程运行的结果);
- 创建MyCallable的对象(表示多线程要执行的任务);
- 创建FutureTask的对象(作用管理多线程运行的结果);
- 创建Thread类的对象,并启动(表示线程);
package com.caihongjia.a0threadcase3;
import com.caihongjia.a0threadcase2.MyRun;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
public class ThreadDemo {
public static void main(String[] args) throws ExecutionException, InterruptedException {
//创建MyCallable的对象(表示多线程要执行的任务);
MyCallable mc = new MyCallable();
//创建FutureTask的对象(作用管理多线程运行的结果);
FutureTask<Integer> ft = new FutureTask<>(mc);
//创建Thread类的对象,并启动(表示线程);
Thread t = new Thread(ft);
t.start();
//获取多线程运行的结果
Integer i = ft.get();
System.out.println(i);
}
}
package com.caihongjia.a0threadcase3;
import java.util.concurrent.Callable;
public class MyCallable implements Callable<Integer> {
@Override
public Integer call() throws Exception {
int sum = 0;
for (int i = 1; i <= 100; i++) {
sum += i;
}
return sum;
}
}
方式对比:
常见的成员方法:
String getName() 返回此线程的名称
void setName(String name) 设置线程的名字(构造方法也可以设置名字)
static Thread currentThread() 获取当前线程的对象
static void sleep(long time) 让线程休眠指定的时间,单位为毫秒
setPriority(int newPriority) 设置线程的优先级
final int getPriority() 获取线程的优先级
final void setDaemon(boolean on) 设置为守护线程
public static void yield() 出让线程/礼让线程
public static void join() 插入线程/插队线程
细节:
String getName() 返回此线程的名称
void setName(String name) 设置线程的名字(构造方法也可以设置名字)
细节:
1.如果我们没有给线程设置名字,线程也是有默认的名字的
格式:Thread-X(x序号,从0开始的)
2.如果我们要给线程设置名字,可以用setName方法进行设置,也可以构造方法设置
static Thread currentThread() 获取当前线程的对象
细节:
当JVM虚拟机启动之后,会自动的启动多条线程
其中有一条线程就叫做main线程
他的作用就是去调用main方法,并执行里面的代码
在以前,我们写的所有的代码,其实都是运行在main线程当中
static void sleep(long time) 让线程休眠指定的时间,单位为毫秒
细节:
1.那条线程执行到这个方法,那么那条线程就会在这里停留对应的时间
2.方法的参数: 就表示睡眠的时间,单位毫秒
3.当时间到了之后,线程会自动的醒来,继续执行下面的其他代码
setPriority(int newPriority) 设置线程的优先级
final int getPriority() 获取线程的优先级
细节:
默认优先级为5; 最大优先级为10; 最小优先级为1;
final void setDaemon(boolean on) 设置为守护线程
细节:
当其他的非守护线程执行完毕之后,守护线程会陆续结束;