目录
Java多线程(二)
线程的生命周期(6种状态)
- 新建状态(new):新建了一个线程,但还未启动时的状态。Thread t = new Thread();
- 就绪状态(Runnable):线程创建成功之后调用了start()方法就进入了Runnable状态。t.start();
- 阻塞状态(Blocked):线程在等待一个监视器锁进入同步代码块/同步方法,或调用Object.wait()方法就可能进入阻塞状态,此时需要使用notify() / notifyAll() 才能唤醒;
- 等待状态(waiting):在线程调用了Object.wait() / notify() / notifyAll() ,thread.join() , LockSupport.park()方法后会进入等待状态;
- 超时等待(Timed_wait):相比较等待状态来说,超时等待状态多了时间限制,等待线程在指定时间内完成任务;
- 终止状态(Terminated):当线程执行完毕后就会进入终止态;
线程的方法及源码解析
1. start() 方法
启动线程,并将线程添加到一个线程组里,线程就会进入到Runnable状态,获取资源进而运行run()方法;
thread.start();
2. sleep() 方法
sleep方法会是线程睡眠一段时间,调用sleep方法下线程进入阻塞状态,不会放弃moniter权限
thread.sleep();
3. yeild() 方法
用了yield方法后,该线程就会把CPU时间让掉,让其他或者自己的线程执行(也就是谁先抢到谁执行);
Thread.yield();
注:yeild方法和sleep方法的区别:sleep方法指挥让当前线程暂停一段时间,不会放弃cpu时间片,在sleep方法调用interrupt方法后,可以捕捉到中断信号;而yeild方法可能会放弃一次cpu的时间片,调用yeild方法会使得线程从Running状态切换到Runnable状态,而且调用了yeild方法调用interrupt方法不能捕捉到中断信号;
4. join() 方法
线程A调用join方法,会使得线程A调用join方法时所在的线程B进入到等待队列, *此时必须等到线程A执行完或者到达给定的时间, 线程B才可以去执行;
thread.join();
5. currentThread()方法
currentThread()方法可返回代码段正在被哪个线程调用的信息。
Thread.currentThread().getName();
6. isAlive()方法
方法isAlive()的功能是判断当前的线程是否处于活动状态;
thread.isAlive();
7. getId()方法
getId()方法的作用是取得线程的唯一标识;
thread.getId();
join()方法的应用演示
例如:创建两个线程(都输出5、4、3、2、1),在一个线程完成输出后另一个线程才能输出
class myThread2 extends Thread{
@Override
public void run(){
for(int i = 5;i > 0;i--){
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("线程2:"+i);
}
}
}
public class twoThread {
public static void main(String[] args) {
// TODO Auto-generated method stub
myThread2 th2 = new myThread2();
th2.start();
for(int i = 5;i > 0;i--){
try {
Thread.sleep(50);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("线程1:"+i);
}
}
}
线程默认优先级为5,所以上面的代码两个线程的优先级等级都是5,两个线程都在打印5 4 3 2 1运行结果如下:
(注:此处因为在学校机房上课随手写的代码,所以是在eclipse上运行的,平时的代码都是IDEA运行的)
如果要实现线程2打印54321完成之后线程1的54321才能开始打印输出的话,使用join()方法:
class myThread2 extends Thread{
@Override
public void run(){
for(int i = 5;i > 0;i--){
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("线程2:"+i);
}
}
}
public class twoThread {
public static void main(String[] args) {
// TODO Auto-generated method stub
myThread2 th2 = new myThread2();
try {
th2.join();
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
th2.start();
for(int i = 5;i > 0;i--){
try {
Thread.sleep(50);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("线程1:"+i);
}
}
}
这样不论运行几次,运行结果都是线程2在线程1前面打印:
多个线程实现模拟航班查询
题目:起四个线程代表四个航空公司,主线程在查询完几个航空公司的信息之后,再返回我们要查询的航班信息
import java.util.ArrayList;
import java.util.Scanner;
class flyCompany extends Thread{
ArrayList<String> list = null;
String name;
String[] from = {"北京","哈尔滨","上海","沈阳"};
String[] arri = {"咸阳","成都","深圳","广州"};
String fromCity = "";
String arrCity = "";
public void set(String fromCity,String arrCity){
this.fromCity = fromCity;
this.arrCity = arrCity;
}
public flyCompany(ArrayList<String> list,String name){
this.list = list;
this.name = name;
}
public String threadName(){
return name;
}
@Override
public void run() {
find();
}
public void find(){
String result;
for(int i = 0;i < from.length;i++){
if(from[i].equals(fromCity)){
for(int j = 0;j < arri.length;j++){
if(arri[j].equals(arrCity)){
result = "From " + from[i] + " to " + arri[j] + ":" + threadName();
list.add(result);
try {
Thread.currentThread().sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
}
}
public class flySystemTest {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
flyCompany flyThread1 = new flyCompany(list,"首都航空");
flyCompany flyThread2 = new flyCompany(list,"海南航空");
flyCompany flyThread3 = new flyCompany(list,"东方航空");
flyCompany flyThread4 = new flyCompany(list,"南方航空");
Scanner sc = new Scanner(System.in);
System.out.println("请输入起点:");
String from = sc.nextLine();
System.out.println("请输入终点:");
String end = sc.nextLine();
flyThread1.set(from,end);
flyThread2.set(from,end);
flyThread3.set(from,end);
flyThread4.set(from,end);
try {
flyThread1.join();
flyThread2.join();
flyThread3.join();
flyThread4.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
flyThread1.start();
flyThread2.start();
flyThread3.start();
flyThread4.start();
for(int i = 0;i < list.size();i++){
System.out.println(list.get(i));
}
}
}
本题目主要体现线程join方法,join方法确保了查询哥哥航空的航班信息这个操作在打印输出结果之前完成,另外,这里我们输入起点和终点之后如果存在这趟航班肯定会四个航空公司均有,因为我这里起的四个查询线程均查询的是同样的数据来源,也就是:
String[] from = {"北京","哈尔滨","上海","沈阳"};
String[] arri = {"咸阳","成都","深圳","广州"};
这部分内容,如果想要各个航空公司航班信息区别开来,只需要改变传入数据即可;