- 什么是多线程?
有了多线程,我们可以让程序同时做多件事情 - 多线程的作用
提高效率
并发
在同一时刻,有多个指令在单个cpu上交替执行
并行
在同一时刻,有多个指令在多个cpu上同时执行
Java多线程的实现方法
- 继承Thread方法
public class ThreadDemo extends Thread{
public static void main(String[] args) {
MyThread t1 = new MyThread();
MyThread t2 = new MyThread();
t1.setName("线程1");
t2.setName("线程2");
t1.start();//start才是开启线程,run仅仅为调用方法
t2.start();
}
}
public class MyThread extends Thread {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(getName()+"helloworld"+i);
}
}
}
- 实现Runnable接口
//创建MyRunnable的对象
//表示多线程要执行的任务
MyRunnable mr = new MyRunnable();
//创建线程对象
Thread t3 = new Thread(mr);
Thread t4 = new Thread(mr);
t3.setName("线程3");
t4.setName("线程4");
//开启线程
t3.start();
t4.start();
public class MyRunnable implements Runnable {
@Override
public void run() {
//书写线程要执行的方法
for (int i = 0; i < 100; i++) {
//获取当前线程的对象
Thread t = Thread.currentThread();
System.out.println(t.getName()+"helloworld");
}
}
}
- 利用Callable接口和Future接口实现
特点:可以获取到多线程的运行结果,是对上面两种方法的补充
//创建MyCallable的对象
MyCallable mc = new MyCallable();
//创建FutureTask的对象(FutureTask是接口Future的实现类,作用是管理多线程运行的结果)
FutureTask<Integer> task = new FutureTask<>(mc);
//创建线程的对象
Thread t5 = new Thread(task);
//启动线程
t5.start();
//获取多线程运行的结果
Integer result = task.get();
System.out.println(result);
public class MyCallable implements Callable<Integer> {
@Override
public Integer call() throws Exception {
//开启线程,求1-100之间的和
int sum = 0;
for (int i = 0; i <= 100; i++) {
sum = sum+i;
}
return sum;
}
}
多线程三种实现方式对比
常见的成员方法
线程的调度
- 抢占式调度
多个线程抢夺cpu的执行权,cpu在什么时候执行哪个线程是不确定的,执行的时间也是不确定的,体现的是随机性 - 非抢占式调度
所有的线程轮流执行,执行的时间也是差不多的
Java中采取的是抢占式调度
Java线程的优先级
//表示多线程要执行的任务
MyRunnable mr = new MyRunnable();
//创建线程对象
Thread t3 = new Thread(mr);
Thread t4 = new Thread(mr);
/*
默认是5,最小为1,最大为10,优先级越高,抢到cpu的概率就越高
*/
System.out.println(t3.getPriority());
System.out.println(t4.getPriority());
设置守护线程
/*
细节:
但其他的非守护线程执行完毕之后,守护线程会陆续结束
通俗易懂:
当女神线程结束了,备胎线程也没有存在的必要了,不是立即结束,是陆续结束
*/
MyThread thread1 = new MyThread();
MyThread2 thread2 = new MyThread2();
thread1.setName("女神");
thread2.setName("备胎");
//将thread2设置为守护线程(备胎线程)
thread2.setDaemon(true);
thread1.start();
thread2.start();
应用场景:在聊天的场景中,用户之间发送文件,如果当聊天窗口关闭了,文件的发送也就没有必要了,就可以把发送文件的线程设置为守护线程
礼让线程
yield()方法,表示让出当前cpu的执行权
插入线程
public class JoinThread {
public static void main(String[] args) throws InterruptedException {
MyThread t = new MyThread();
t.setName("线程1");
t.start();
/*
join方法,表示把当前t这个线程,插入到当前线程(main线程)之前
等t线程里的方法都执行完了,才执行main线程内的代码
*/
t.join();
for (int i = 0; i < 10; i++) {
System.out.println("main线程"+i);
}
}
}