多线程de小事情
导航不迷路:- 程序、进程以及线程的爱恨情仇
- 最简单实现多线程的方法(Thread)
- 简单易懂的多线程(通过实现Runnable接口实现多线程)
- 常用获取线程基本信息的方法(新手专属)
- 多线程别怕,有锁就安全;(解决线程安全问题)
文章目录
预备知识:
在探索多线程安全问题之前,我们需要了解一些相关知识;
线程的状态
1.新生状态;
用new关键字创建一个线程后,这个线程就是出于新生状态;
2.就绪状态;
线程的Start()方法被调用后,等待分配CPU时就是处于就绪状态(也称之为有资源无资格);
3.运行状态;
线程的run()方法被执行,被CPU选中;(有资源,有资格)
4.阻塞状态;
暂停某个线程的执行,等待某个条件的发生;
有四种原因导致阻塞状态;
1.执行sleep()方法,使当前线程休眠,处于阻塞状态;当指定时间到达后进入就绪状态;
代码如下:
package com.bjsxt.threadMethod;
public class MyThreadSleep implements Runnable{
@Override
public void run() {
try {
System.out.println("my线程睡着了");
Thread.sleep(1000);
System.out.println("my线程醒了");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
测试类代码:
package com.bjsxt.threadMethod;
public class TestSleep {
public static void main(String[] args) throws InterruptedException {
MyThreadSleep my = new MyThreadSleep();
Thread t = new Thread(my);
t.start();
System.out.println("主线程睡着");
Thread.sleep(2000);
System.out.println("主线程醒了");
}
}
运行效果:
2.执行wait()方法,使当前线程进入阻塞状态,当调用notify()方法唤醒这个线程后,进入就绪状态;
暂时不做演示:在后续生产者、消费者模式中进行演示;
3.Join()线程联合:当某个线程需要等待另一个线程执行结束后,才能执行是使用join()方法;
代码如下:
public class MyThreadJoin1 implements Runnable{
@Override
public void run() {
for(int i=0;i<10;i++) {
System.out.println(Thread.currentThread().getName()+"----"+i);
}
}
}
测试类代码:
public class TestJoin1 {
public static void main(String[] args) throws InterruptedException {
MyThreadJoin my = new MyThreadJoin();
Thread t = new Thread(my);
t.start();
for(int i=0;i<10;i++) {
if(i==2) {
t.join();
}
System.out.println("----------"+Thread.currentThread().getName()+"---"+i);
}
}
}
运行效果:
4.线程运行时,某个操作进入阻塞状态,比如io流(read(),write()方法本身就是阻塞的 方法)只有当阻塞原因消失后,线程才会进入就绪状态;
5.死亡状态;
死亡状态是线程的最后一个状态;
导致死亡状态有两个原因;
1.线程正常执行结束;
2.强制终止线程;
当线程处于死亡状态后,不能再回到其他状态;
多线程在访问共享资源时的确有优点,速度快;但是会出现安全性问题,数据错乱;
案例:设计一个火车售票模拟程序;假如只剩五张票,三个窗口同时售票,每个窗口都有100人在排队;
车票类代码:
public class Ticket implements Runnable{
private int ticket=5;
@Override
public void run() {
for(int i=0;i<100;i++) {
if(ticket>0) {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"正在卖第"+ticket--+"张票");
}
}
}
}
测试类代码
public class TestTicket {
public static void main(String[] args) {
Ticket t = new Ticket();
Thread thread1 = new Thread(t,"A窗口");
Thread thread2 = new Thread(t,"B窗口");
Thread thread3 = new Thread(t,"B窗口");
thread1.start();
thread2.start();
thread3.start();
}
}
效果图:
如图所示由于多线程的安全问题导致数据错乱的问题;
つづく…
感谢您的观看;后续仍然会不断更新多线程,最终会以生产者消费者模式的小项目结束;
敬请期待;