多线程
-
什么时多线程?
我们在生活中,比如打游戏,为什么可以和自己的好友一起玩游戏,在游戏中可以看到自己和自己的好友,并且各自可以完成自己的事情。其实就是在一定时间内能够执行多于一个的线程。 -
多任务:一边吃饭一边玩手机、边上厕所边玩手机。
-
进程(Process):在操作系统中执行的程序就是进程,比如扣扣、游戏‘播放器等。进程则是执行程序的一次执行过程,它是一个动态的概念,是系统资源分配的单位。一个进程可以有多个线程,在视频中可以看图像、听声音、看弹幕。
注意:很多多线程是模拟出来的,真正的多线程是指有多个cpu,即多核,如服务器。如果多线程是模拟出来的,即在同一个cpu下,同一个时间点,cpu只能执行一个代码,因为切换的很快,所有就有同时执行的错觉。 -
线程实现
- 写一个类继承成Thread类,重写run()方法
- Thread类也是实现了Runnable接口
package 多线程;
public class DownloaderFile extends Thread{
@Override
public void run() {
for (int i = 0; i < 20; i++) {
System.out.println("学习多线程");
}
}
public static void main(String[] args) {
DownloaderFile df = new DownloaderFile();
//开启线程
df.start();
for (int i = 0; i < 200; i++) {
System.out.println("main主线程");
}
}
}
- 定义一个类实现Runnable接口
package 多线程;
//Thread类也是实现了Runnable接口 // 重写run方法
public class TwoThread implements Runnable{
@Override
public void run() {
for (int i = 0; i < 20; i++) {
System.out.println("学习多线程");
}
}
public static void main(String[] args) {
TwoThread th = new TwoThread();
//方法一
// Thread thread = new Thread(th);
// thread.start();
//方法二
new Thread(th).start();
for (int i = 0; i < 200; i++) {
System.out.println("main主线程");
}
}
}
-
定义一个类实现callable接口
-
线程紊乱
当多个线程同时操作一个对象时,可能会发生线程紊乱,数据错误。
比如模拟买票程序,代码如下
package 多线程;
public class TestThread implements Runnable{
//票数
private int ticketNums = 10;
@Override
public void run() {
while (true){
if(ticketNums<=0){
break;
}
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//Thread.currentThread().getName() 获得当前线程的名字
System.out.println(Thread.currentThread().getName()+"拿到了第几张"+ticketNums--+"票");
}
}
public static void main(String[] args) {
TestThread testThread = new TestThread();
//模拟实现一个买票程序
new Thread(testThread,"啊成").start();
new Thread(testThread,"啊德").start();
new Thread(testThread,"啊杰").start();
}
}
//运行结果如下
啊成拿到了第几张10票
啊德拿到了第几张9票
啊杰拿到了第几张8票
啊德拿到了第几张7票
啊成拿到了第几张6票
啊杰拿到了第几张5票
啊德拿到了第几张4票
啊杰拿到了第几张3票
啊成拿到了第几张3票
啊德拿到了第几张2票
啊成拿到了第几张1票
啊杰拿到了第几张1票
啊德拿到了第几张0票
在上面的程序中会发现,两个人会同时拿到一张票,这样明显不符合实际情况。可以通过线程睡眠进行解决。
- 线程状态
创建状态:当new Thread()时就进入新生创建状态;
就绪状态:当调用start()方法时进入就绪状态,但不是立即执行,要等待cpu调度执行;
阻塞状态:当调用了sleep,wait或者同步锁时进入阻塞状态,此时就是部往下执行代码,当阻塞状态解除后,从新进入就绪状态,等待cpu的调度;
运行状态:进入运行状态,才是正真的执行线程体代码块。
死亡状态:线程终止 - 线程方法
1.setPriority(int newPriority) 用来更改线程优先级
2.static void sleep(long mills) 在指定的毫秒数让当前正在执行的线程体休眠
3.void join() 等待给线程终止
4.static void yield() 暂停当前正在执行的线程对象,并执行其他线程
5.void interrupt() 中断线程,不推荐使用这个方法
6.boolean isAlie() 测试线程是否处于活动状态