首页 >> 大全

【Java 并发编程】【03】Thread类API

2024-01-10 大全 37 作者:考证青年

类API 1 创建线程对象相关

构造器:

2 线程体和启动线程 2.1 run()

void run()

2.2 start() 3 获取和设置线程信息 ()

():这是一个静态方法,返回当前正在执行的线程对象

()

final ():测试线程是否处于活动状态。如果线程已经启动且尚未终止,则为活动状态。

()

final ():()方法是的实例方法,该方法返回当前线程对象的名字

( name)

final void ( name):设置该线程名称。除了主线程main之外,其他线程可以在创建时指定线程名称或通过( name)方法设置线程名称,否则依次为-0,-1…等。

()

final int () :返回线程优先级

(int )

final void (int ) :改变线程的优先级

4 控制线程

类提供了一些方法,可以控制线程的执行。

1、线程睡眠:sleep

1.API 官方描述

/** Causes the currently executing thread to sleep (temporarily cease execution) for the specified number of milliseconds, subject to the precision and accuracy of system timers and schedulers. The thread does not lose ownership of any monitors.
Params:
millis – the length of time to sleep in milliseconds
Throws:
IllegalArgumentException – if the value of millis is negative
InterruptedException – if any thread has interrupted the current thread. The interrupted status of the current thread is cleared when this exception is thrown.
public static native void sleep(long millis) throws InterruptedException;
*/
public static void sleep(long millis, int nanos)throws InterruptedException {if (millis < 0) {throw new IllegalArgumentException("timeout value is negative");}if (nanos < 0 || nanos > 999999) {throw new IllegalArgumentException("nanosecond timeout value out of range");}if (nanos >= 500000 || (nanos != 0 && millis == 0)) {millis++;}sleep(millis);}

2.细节补充

3..sleep()的等价方法

TimeUnit.SECONDS.sleep(1);//Thread.sleep(1000);

4.使用练习:实现倒计时

并发编程是不是多线程_并发编程有什么用_

实现十秒倒计时

public class _01_Sleep {public static void main(String[] args) {new Thread(new Runnable() {@Overridepublic void run() {System.out.println("倒计时预备:");for (int i = 10; i > 0 ; i--) {System.out.println(i);try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}System.out.println("新年快乐!");}}, "倒计时").start();}
}

Sleep应用场景 - 减少对cpu的占用

2、线程让步:yield

public static native void yield();

public class _02_yield {public static void main(String[] args) {MyYieldThread m1 = new MyYieldThread("低");m1.setPriority(Thread.MIN_PRIORITY);MyYieldThread m2 = new MyYieldThread("高");m2.setPriority(Thread.MAX_PRIORITY);m1.start();m2.start();}}class MyYieldThread extends Thread {public MyYieldThread(String name) {super(name);}public void run() {for (int i = 1; i <= 10; i++) {System.out.println(getName() + ":" + i);Thread.yield();}}
}:1:2:3:4:5:6:7:8:9:10:1:2:3:4:5:6:7:8:9:10

可以看出,即便线程让出cpu进入就绪态,但是下一次继续被cpu执行的概率还是挺大的

3、线程加塞:join

void join()   等待该线程终止。 
void join(long millis) :等待该线程终止的时间最长为 millis 毫秒。如果millis时间到,将不再等待。 
void join(long millis, int nanos) :等待该线程终止的时间最长为 millis 毫秒 + nanos 纳秒。 

示例代码:

public class _03_join {public static void main(String[] args) {ChatThread t = new ChatThread();t.start();for (int i = 1; i < 10; i++) {System.out.println("main:" + i);try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();}//当main打印到5之后,需要等join进来的线程停止后才会继续了。if(i==5){try {t.join();} catch (InterruptedException e) {e.printStackTrace();}}}}
}class ChatThread extends Thread{public void run(){Scanner input = new Scanner(System.in);while(true){System.out.println("是否结束?(Y、N)");char confirm = input.next().charAt(0);if(confirm == 'Y' || confirm == 'y'){break;}}input.close();}
}main:1
main:2
main:3
是否结束?(YN)
main:4
main:5
N
是否结束?(YNN
是否结束?(YNN
是否结束?(YNY
main:6
main:7
main:8
main:9

join 应用

4 、线程中断:

(1)每个线程都一个状态位用于标识当前线程对象是否是中断状态。

(2)

public boolean isInterrupted()
public void interrupt()
public static boolean interrupted() 

(3)()

public boolean isInterrupted() {return isInterrupted(false);
}private native boolean isInterrupted(boolean ClearInterrupted);

底层调用的本地方法,传入一个类型的参数,用于指定调用该方法之后是否需要清除该线程对象的中断标识位。从这里我们也可以看出来,调用并不会清除线程对象的中断标识位。

案例1

编写龟兔赛跑多线程程序,设赛跑长度为30米

兔子的速度是10米每秒,兔子每跑完10米休眠的时间10秒

乌龟的速度是1米每秒,乌龟每跑完10米的休眠时间是1秒

要求:要等兔子和乌龟的线程结束,主线程(裁判)才能公布最后的结果。

package com.atguigu.part02;public class Racer extends Thread {private String name;//运动员名字private long runTime;//每米需要时间,单位毫秒private long restTime;//每10米的休息时间,单位毫秒private long distance;//全程距离,单位米private long time;//跑完全程的总时间public Racer(String name, long distance, long runTime, long restTime) {super();this.name = name;this.distance = distance;this.runTime = runTime;this.restTime = restTime;}@Overridepublic void run() {long sum = 0;long start = System.currentTimeMillis();while (sum < distance) {System.out.println(name + "正在跑...");try {Thread.sleep(runTime);// 每米距离,该运动员需要的时间} catch (InterruptedException e) {return ;}sum++;try {if (sum % 10 == 0 && sum < distance) {// 每10米休息一下System.out.println(name+"已经跑了"+sum+"米正在休息....");Thread.sleep(restTime);}} catch (InterruptedException e) {return ;}}long end = System.currentTimeMillis();time = end - start;System.out.println(name+"跑了"+sum+"米,已到达终点,共用时"+time/1000.0+"秒");}public long getTime() {return time;}}

package com.atguigu.part02;public class TestJoin2 {public static void main(String[] args) {Racer rabbit = new Racer("兔子", 30, 100, 10000);Racer turtoise = new Racer("乌龟", 30, 1000, 1000);rabbit.start();turtoise.start();try {rabbit.join();} catch (InterruptedException e) {e.printStackTrace();}try {turtoise.join();} catch (InterruptedException e) {e.printStackTrace();}//因为要兔子和乌龟都跑完,才能公布结果System.out.println("比赛结束");System.out.println(rabbit.getTime()<turtoise.getTime()?"兔子赢":"乌龟赢");}
}

4、守护线程

概念:有一种线程,它是在后台运行的,它的任务是为其他线程提供服务的,这种线程被称为“守护线程”。JVM的垃圾回收线程就是典型的守护线程。

特点:

守护线程有个特点,就是如果所有非守护线程都死亡,那么守护线程自动死亡。

使用:

(1)将线程设置为守护线程

调用(true)方法可将指定线程设置为守护线程。必须在线程启动之前设置,否则会报异常。

(2)判断是否是守护线程

调用()可以判断线程是否是守护线程。

package com.atguigu.part02;public class TestDaemon {public static void main(String[] args) {MyDaemon m = new MyDaemon();m.setDaemon(true);m.start();for (int i = 0; i < 20; i++) {System.out.println("main:" + i);}}
}
class MyDaemon extends Thread{public void run(){while(true){System.out.println("MyDaemon");try {Thread.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}}}
}

执行效果就是等main线程执行完,才会执行守护线程;

5、使用标识来停止线程

我们知道线程体执行完,或遇到未捕获的异常自然会停止,但是有时我们希望由另一个线程检测到某个情况时,停止一个线程,该怎么做呢?

类提供了stop()来停止一个线程,但是该方法具有固有的不安全性,已经标记为@不建议再使用,那么我们就需要通过其他方式来停止线程了,其中一种方式是使用标识。

案例:编写龟兔赛跑多线程程序,设赛跑长度为30米

兔子的速度是10米每秒,兔子每跑完10米休眠的时间10秒

乌龟的速度是1米每秒,乌龟每跑完10米的休眠时间是1秒

要求:只要兔子和乌龟中有人到达终点,就宣布比赛结束,没到达终点的也停下来。

package com.atguigu.part02;public class Player extends Thread{private String name;//运动员名字private long runTime;//每米需要时间,单位毫秒private long restTime;//每10米的休息时间,单位毫秒private long distance;//全程距离,单位米private long time;//跑完全程的总时间private boolean flag = true;     //true 表示继续跑 false表示结束线程private volatile boolean ended = false;//用于标记是否到达终点public Player(String name, long distance, long runTime, long restTime) {super();this.name = name;this.distance = distance;this.runTime = runTime;this.restTime = restTime;}@Overridepublic void run() {long sum = 0;long start = System.currentTimeMillis();while (sum < distance && flag) {System.out.println(name + "正在跑...");try {Thread.sleep(runTime);// 每米距离,该运动员需要的时间} catch (InterruptedException e) {return ;}sum++;try {if (sum % 10 == 0 && sum < distance && flag) {// 每10米休息一下System.out.println(name+"已经跑了"+sum+"米正在休息....");Thread.sleep(restTime);}} catch (InterruptedException e) {return ;}}long end = System.currentTimeMillis();time = end - start;ended = sum == distance ? true : false;System.out.println(name+"跑了"+sum+"米,共用时"+time/1000.0+"秒");}public long getTime() {return time;}public void setFlag(boolean flag) {this.flag = flag;}public boolean isEnded() {return ended;}}

package com.atguigu.part02;public class TestStop {public static void main(String[] args) {Thread.currentThread().setPriority(Thread.MAX_PRIORITY);Player rabbit = new Player("兔子", 30, 100, 10000);Player turtoise = new Player("乌龟", 30, 1000, 1000);rabbit.start();turtoise.start();while(true){if(rabbit.isEnded() || turtoise.isEnded()){rabbit.setFlag(false);                           turtoise.setFlag(false);                          //只要又人跑完,就结束比赛,并公布结果break;}}System.out.println("比赛结束");if(rabbit.isEnded() && turtoise.isEnded()){System.out.println(rabbit.getTime()<turtoise.getTime()?"兔子赢":"乌龟赢");}else if(rabbit.isEnded()){System.out.println("兔子赢");}else if(turtoise.isEnded()){System.out.println("乌龟赢");}}
}

tags: 线程

关于我们

最火推荐

小编推荐

联系我们


版权声明:本站内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 88@qq.com 举报,一经查实,本站将立刻删除。备案号:桂ICP备2021009421号
Powered By Z-BlogPHP.
复制成功
微信号:
我知道了