了解java多线程
一、进程和线程简介
1.什么是进程和线程
一个程序就是一个进程,而一个程序中的多个任务则被称为线程。
进程是表示资源分配的基本单位,线程是进程中执行运算的最小单位,亦是调度运行的基本单位。
2.什么是多线程
多线程就是多个线程同时运行或交替运行。单核CPU的话是顺序执行,也就是交替运行。多核CPU的话,因为每个CPU有自己的运算器,所以在多个CPU中可以同时运行。
3.多线程的好处:
1.可以充分利用CPU资源
2.提高用户体验
二、如何使用多线程
1.继承Thread类
1.创建一个集成于Thread类的子类 (通过ctrl+o(override)输入run查找run方法)
2.重写Thread类的run()方法
3.创建Thread子类的对象
4.通过此对象调用start()方法
start与run方法的区别: start方法的作用:
1.启动当前线程
2.调用当前线程的重写的run方法(在主线程中生成子线程,有两条线程) 调用start方法以后,一条路径代表一个线程,同时执行两线程时,因为时间片的轮换,所以执行过程随机分配,且一个线程对象只能调用一次start方法。
run方法的作用:在主线程中调用以后,直接在主线程一条线程中执行了该线程中run的方法。(调用线程中的run方法,只调用run方法,并不新开线程)总结:我们不能通过run方法来新开一个线程,只能调用线程中重写的run方法(可以在线程中不断的调用run方法,但是不能开启子线程,即不能同时干几件事),start是开启线程,再调用方法(即默认开启一次线程,调用一次run方法,可以同时执行几件事)
public class modeThread extends Thread{
@Override
public void run() {
for (int i=0;i<20;i++){
System.out.println(i+"你好,我是来自线程:"+Thread.currentThread().getName());
}
}
public static void main(String[] args) {
modeThread t1=new modeThread();
modeThread t2=new modeThread();
t1.start();
t2.start();
}
}
运行结果
你好,我是来自线程:Thread-0
你好,我是来自线程:Thread-1
你好,我是来自线程:Thread-1
你好,我是来自线程:Thread-1
你好,我是来自线程:Thread-1
你好,我是来自线程:Thread-1
你好,我是来自线程:Thread-1
你好,我是来自线程:Thread-0
你好,我是来自线程:Thread-0
你好,我是来自线程:Thread-0
你好,我是来自线程:Thread-0
你好,我是来自线程:Thread-0
你好,我是来自线程:Thread-0
你好,我是来自线程:Thread-0
你好,我是来自线程:Thread-0
你好,我是来自线程:Thread-0
你好,我是来自线程:Thread-1
你好,我是来自线程:Thread-1
你好,我是来自线程:Thread-1
你好,我是来自线程:Thread-1
2.实现Runable接口方式
1.创建一个实现了Runable接口的类
2.实现类去实现Runnable中的抽象方法:run()
3.创建实现类的对象
4.将此对象作为参数传递到Thread类中的构造器中,创建Thread类的对象
5.通过Thread类的对象调用start()
public class MyThread1 implements Runnable {
public static void main(String[] args) {
//创建线程对象
MyThread1 mt1=new MyThread1();
Thread t1=new Thread(mt1);
Thread t2=new Thread(mt1);
t1.setName("t1");
t2.setName("t2");
t1.start();
t2.start();
}
@Override
public void run() {
for (int i=1;i<10;i++){
System.out.println(Thread.currentThread().getName()+"\t"+i);
}
}
}
运行结果
t2 1
t1 1
t2 2
t1 2
t2 3
t1 3
t2 4
t1 4
t2 5
t1 5
t2 6
t1 6
t2 7
t2 8
t2 9
t1 7
t1 8
t1 9
三、线程的生命周期
新建 | 当一个Thread类或其子类的对象被声明并创建时,新生的线程对象处于新建状态 |
---|---|
就绪 | 处于新建状态的线程被start后,将进入线程队列等待CPU时间片,此时它已具备了运行的条件,只是没分配到CPU资源 |
运行 | 当就绪的线程被调度并获得CPU资源时,便进入运行状态,run方法定义了线程的操作和功能 |
阻塞 | 在某种特殊情况下,被人为挂起或执行输入输出操作时,让出CPU并临时终止自己的执行,进入阻塞状态 |
死亡 | 线程完成了它的全部工作或线程被提前强制性地中止或出现异常导致结束 |
四、线程调度方法
1.setPriority:改变线程的优先级,改变线程抢占资源的概率,但是不绝对
2.Sleep(毫秒数):在指定时间内让当前线程释放CPU资源,转入阻塞状态 指定时间结束后转入就绪状态,和其他线程抢占资源
3.join:让当前线程A暂停执行,将资源让给插队的线程b;当b完成执行以后再再讲资源还给A
4.Yeild:线程礼让,让当前线程释放CPU资源,可以给其他线程提供机会,自己转入就绪状态,继续和其他线程抢占资源
5.Interrupt:强行中断
6.isAlive:判断某个线程是否处于活动状态
五、线程普通方法
1.getPriority:获取当前线程的优先级
2.GetName:获取当前线程的名字
3.SetName:给当前线程设置名字
六、线程同步:确保在同一时刻只有一个线程访问当前资源
实现方式
1.同步方法:public synchronized void run(){}
2.同步代码块:
Public void run(){
synchronized(资源,一般是属性名称){代码块}
}
七、线程安全:实现线程同步的类被认为线程安全,否则不安全
1.安全:HashTable/StringBuffer
2.不安全:HashMap/StringBuilder
Ps:线程安全的效率低