多线程-基本概念
2019-07-17 本文已影响0人
Scorw
进程是所有线程的集合,每一个线程是进程中的一条执行路径。
- 耗时的操作使用线程,提高应用程序的相应速度。
- 并行操作时使用线程,如C/S架构的服务器并发线程响应的请求。
- 多CPU系统中,使用线程提高CPU利用率。
- 改善程序结构,一个既长又复杂的进程可以考虑分为多个线程,成为几个独立或者半独立的运行部分,这样的程序会利于理解和修改。
- 第一种继承Thread类 重写run方法
class CreateThread extends Thread {
// run方法中编写 多线程需要执行的代码
public void run() {
for (inti = 0; i< 10; i++) {
System.out.println("i:" + i);
}
}
}
public class ThreadDemo {
public static void main(String[] args) {
System.out.println("-----多线程创建开始-----");
// 1.创建一个线程
CreateThread createThread = new CreateThread();
// 2.开始执行线程 注意 开启线程不是调用run方法,而是start方法
System.out.println("-----多线程创建启动-----");
createThread.start();
System.out.println("-----多线程创建结束-----");
}
}
- 第二种实现Runnable接口,重写run方法
class CreateRunnable implements Runnable {
@Override
public void run() {
for (inti = 0; i< 10; i++) {
System.out.println("i:" + i);
}
}
}
publicclass ThreadDemo2 {
public static void main(String[] args) {
System.out.println("-----多线程创建开始-----");
// 1.创建一个线程
CreateRunnable createThread = new CreateRunnable();
// 2.开始执行线程 注意 开启线程不是调用run方法,而是start方法
System.out.println("-----多线程创建启动-----");
Thread thread = new Thread(createThread);
thread.start();
System.out.println("-----多线程创建结束-----");
}
}
- 第三种使用匿名内部类方式
Thread thread = new Thread(new Runnable() {
public void run() {
for (int i = 0; i< 10; i++) {
System.out.println("i:" + i);
}
}
});
thread.start();
System.out.println("-----多线程创建结束-----");
问题一
使用继承Thread类还是使用实现Runnable接口好?
答:使用实现实现Runnable接口好,原因实现了接口还可以继续继承,继承Thread类不能再继承。
问题二
启动线程是使用调用start方法还是run方法?
答:开启线程不是调用run方法,而是start方法;调用run只是使用实例调用方法。
线程分类:
1. 守护线程:
专门用于服务其他的线程,如果其他的线程(即用户自定义线程)都执行完毕,连main线程也执行完毕,那么jvm就会退出(即停止运行)——此时,连jvm都停止运行了,守护线程当然也就停止执行了。
典型守护线程,垃圾回收线程。
2. 用户线程:
用户线程,就是应用程序里的自定义线程。
多线程运行状态
- 创建(new)状态: 准备好了一个多线程的对象
- 就绪(runnable)状态: 调用了start()方法, 等待CPU进行调度
- 运行(running)状态: 执行run()方法
- 阻塞(blocked)状态: 暂时停止执行, 可能将资源交给其它线程使用
-
终止(dead)状态: 线程销毁
多线程的运行状态
问题三
sleep和wait的区别:
sleep是Thread类的方法,wait是Object类中定义的方法.
Thread.sleep不会导致锁行为的改变, 如果当前线程是拥有锁的, 那么Thread.sleep不会让线程释放锁.
Thread.sleep和Object.wait都会暂停当前的线程. OS会将执行时间分配给其它线程. 区别是, 调用wait后, 需要别的线程执行notify/notifyAll才能够重新获得CPU执行时间.
多线程中一些常用api
- join()方法作用:
join作用是让其他线程变为等待, t1.join();// 让其他线程变为等待,直到当前t1线程执行完毕,才释放。
thread.Join把指定的线程加入到当前线程,可以将两个交替执行的线程合并为顺序执行的线程。比如在线程B中调用了线程A的Join()方法,直到线程A执行完毕后,才会继续执行线程B。 - 优先级:
JAVA线程中,通过一个int priority来控制优先级,范围为1-10,其中10最高,默认值为5 - Yield方法:
Thread.yield()方法的作用:暂停当前正在执行的线程,并执行其他线程。
练习题(一):
需求:
- 目前有10万个用户,现在需要做活动,给每一个用户发送一条祝福短信。
源码:代码仓库
执行结果:
线程0,UserEntity [userId=userId:1, userName=userName:1]
线程0,UserEntity [userId=userId:2, userName=userName:2]
线程2,UserEntity [userId=userId:5, userName=userName:5]
线程2,UserEntity [userId=userId:6, userName=userName:6]
线程1,UserEntity [userId=userId:3, userName=userName:3]
线程1,UserEntity [userId=userId:4, userName=userName:4]
线程3,UserEntity [userId=userId:7, userName=userName:7]
线程3,UserEntity [userId=userId:8, userName=userName:8]
线程4,UserEntity [userId=userId:9, userName=userName:9]
线程4,UserEntity [userId=userId:10, userName=userName:10]