Java学习之线程中一些方法,生命周期,线程间通信

来源:互联网 发布:如何将相同的数据合并 编辑:程序博客网 时间:2024/05/22 09:49

一、线程中的一些方法

1、线程加入

public final void join()

使用这个方法后,其他线程必须要在这个线程执行完之后才能继续抢着执行

public class Test {public static void main(String[] args) {//创建线程对象MyThread mt = new MyThread();MyThread mt2 = new MyThread();MyThread mt3 = new MyThread();//设置线程名字mt.setName("大宝");mt2.setName("菲菲");mt3.setName("张益达");//开启线程mt.start();//线程加入try {mt.join();} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}mt2.start();mt3.start();}}

2、线程礼让

public static void yield()

暂停当前正在执行的线程对象,并执行其他程序

作用:让线程间的执行更和谐一些,但是实际上做不到

public class MyThread extends Thread{@Overridepublic void run() {for (int i = 0; i < 10; i++) {System.out.println(this.getName()+":"+i);MyThread.yield();}}}

3、线程死亡

public final void stop():直接杀死

public void interrupt();直接杀死,在死前,还可以有遗言

代码:

类:

package com.edu_03;import java.text.SimpleDateFormat;import java.util.Date;public class MyThread extends Thread{@Overridepublic void run() {System.out.println("开始时间"+new SimpleDateFormat("HH:mm:ss").format(new Date()));try {Thread.sleep(10000);} catch (InterruptedException e) {System.out.println("我已经被杀死了");}System.out.println("开始时间"+new SimpleDateFormat("HH:mm:ss").format(new Date()));}}
主程序:

package com.edu_03;public class Test {public static void main(String[] args) {//创建线程对象MyThread mt = new MyThread();//设置线程名字mt.setName("大宝");//开启线程mt.start();//再睡觉中杀死try {Thread.sleep(3000);//public final void stop():直接杀死//mt.stop();// public void interrupt():直接杀死,在死前,还可以有遗言。mt.interrupt();} catch (Exception e) {// TODO: handle exception}}}

二、线程的生命周期:


三、线程间通信

生产消费者问题不同类型针对同一资源操作
例如:
售票案例:在卖票的同时还要有入票,
买票的窗口可能多个,那么买入票的窗口可能也是多个
案例:
以给学生设置和获取姓名和年龄为例,演示线程通信问题
  线程间通讯:
  资源:Student
  设置数据线程:SetThread
  获取数据线程:GetThread
  测试类:T
代码:
资源:
package com.edu_04;public class Student { String name; int age; boolean flag;}
设置数据线程:
package com.edu_04;//作用:用于给学生对象赋值//在赋值前利用student对象中自带的flag字段进行判断,如果为true说明已经赋了值则让这个线程等待,从而让获取值得线程运行//如果为false则说明没有赋值,则执行下面的判断代码,然后进行赋值,赋值之后吧flag赋值为true,然后唤醒其他等待的代码public class SetThread implements Runnable{private Student s;private int i= 0;//有参构造public SetThread(Student s){this.s = s;}@Overridepublic void run() {while (true) {synchronized (s) {if (s.flag) {//如果flag为true则等待try {s.wait();} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}if (i%2==0) {s.name = "周杰伦";s.age = 35;}else{s.name = "汪峰";s.age = 45;}i++;s.flag=true;//把flag赋值为trues.notify();//唤醒线程,如果有等待的线程则唤醒,如果没有则什么也没有}}}}
获取线程资源:
package com.edu_04;//作用:输出值//先进行判断,如果为false则等待,如果为true则执行下面的代码输出值,同时把flag赋值为false,然后唤醒其他等待的代码public class GetThread implements Runnable{private Student s;public GetThread(Student s){this.s = s;}@Overridepublic void run() {while (true) {synchronized (s) {if(!s.flag){//如果flag为false则等待try {s.wait();} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}System.out.println(s.name+":"+s.age);s.flag = false;s.notify();}}}}
测试类:
package com.edu_04;public class Test {public static void main(String[] args) {//创建学生对象Student s = new Student();//创建线程对象SetThread st = new SetThread(s);GetThread gt = new GetThread(s);Thread sd = new Thread(st);Thread gd = new Thread(gt);//开启线程sd.start();gd.start();}}
为了让设置线程和获取纤尘操作的是同一个资源,把学生对象作为构造参数传了过去,
为了防止初夏线程安全问题,我们加了同一把锁(就是这个传递的参数),为了实现礼让效果,我们加了等待唤醒机制
还可以优化的是把同步代码块改为同步方法,在类中实现:
package com.edu_05;/** * 使用同步方法代替代码块 * */public class Student {private String name;private int age;private boolean flag;public synchronized void setThread(String name,int age){synchronized (this) {if (this.flag) {//如果flag为true则等待try {this.wait();} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}} this.name = name; this.age = age;this.flag=true;//把flag赋值为truethis.notify();//唤醒线程,如果有等待的线程则唤醒,如果没有则什么也没有}}public synchronized void getThread(){synchronized (this) {if(!this.flag){//如果flag为false则等待try {this.wait();} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}System.out.println(this.name+":"+this.age);this.flag = false;this.notify();}}}