类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 millisecondsThrows:IllegalArgumentException – if the value of millis is negativeInterruptedException – 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.使用练习:实现倒计时
文章插图
实现十秒倒计时
【【Java 并发编程】【03】Thread类API】
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:1main:2main:3是否结束?(Y、N)main:4main:5N是否结束?(Y、N)N是否结束?(Y、N)N是否结束?(Y、N)Ymain:6main:7main:8main: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()
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()
- 海贼王剧场版2019什么时候上映
- Costco暂停营业是为什么
- 乔欣家里到底干什么的
- 黄龙玉与翡翠的区别 翡翠与黄龙玉之间的区别
- 手机丢了怎么发朋友圈要电话 手机丢了怎么发朋友圈
- 扭丝饼怎么做 扭丝饼子制作方法
- 钓鲤鱼最好用的饵料有哪些 钓鲤鱼最好用的饵料有哪些品牌
- 长江子鱼的功效与作用 长江子鱼的功效与作用及禁忌
- 智能电饭煲煮饭怎样不粘锅 智能电饭煲煮饭怎样
- 喝可乐会长痘吗 喝可乐会长痘吗女生