停止线程
不推荐使用jdk提供的stop,destroy方法
推荐线程自己停下来
建议使用一个标志位进行终止变量,当flag=false,则终止线程
package state;
/**
* @Classname TestStop
* @Description TODO
* @Date 2020/12/8 9:34
* @Created by mmz
*/
// 建议线程正常停止——>利用次数,不建议死循环
// 建议使用标志位,设置一个标志位
// 不要使用stop,destroy等过时的方法
public class TestStop implements Runnable{
private boolean flag = true;
@Override
public void run() {
int i = 0;
while(flag){
System.out.println("线程正在运行" + i++);
}
}
// 设置一个公开的方法,转换标志位
public void stop(){
this.flag = false;
}
public static void main(String[] args) {
TestStop testStop = new TestStop();
new Thread(testStop).start();
for (int i = 0; i < 1000000; i++) {
// System.out.println("main" + i);
if(i == 90000){
testStop.stop();
System.out.println("线程该停止了");
}
}
}
}
线程休眠
sleep时间指定当前线程阻塞的毫秒数
sleep存在异常InterruptedException
sleep时间达到以后线程进入就绪状态
sleep可以模拟网络延迟,倒计时等
每一个对象都有一个锁,但是sleep不会释放锁
模拟倒计时
package state;
/**
* @Classname TestSleep2
* @Description TODO
* @Date 2020/12/8 9:51
* @Created by mmz
*/
/*模拟倒计时*/
public class TestSleep2 {
public void tenDown(){
int number = 10;
while(true){
try {
Thread.sleep(1000);
System.out.println(number--);
if(number <= 0){
break;
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
TestSleep2 testSleep2 = new TestSleep2();
testSleep2.tenDown();
}
}
模拟时间
package state;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* @Classname TestSleep3
* @Description TODO
* @Date 2020/12/8 9:54
* @Created by mmz
*/
/*打印当前系统的时间*/
public class TestSleep3 {
public static void main(String[] args) {
// 获取系统当前时间
Date time = new Date(System.currentTimeMillis());
while(true){
try {
Thread.sleep(1000);
System.out.println(new SimpleDateFormat("HH:mm:ss").format(time));
time = new Date(System.currentTimeMillis());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
线程礼让
礼让线程,让当前正在执行的线程暂停,但不阻塞
将线程从运行状态转换为就绪状态
让cpu重新调度,礼让不一定成功,还可能cpu选择了刚才礼让出来的线程
package state;
/**
* @Classname TestYield2
* @Description TODO
* @Date 2020/12/8 10:04
* @Created by mmz
*/
public class TestYield2 {
public static void main(String[] args) {
MyYield myYield = new MyYield();
new Thread(myYield,"a").start();
new Thread(myYield,"b").start();
}
}
class MyYield implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "正在执行");
Thread.yield();
System.out.println(Thread.currentThread().getName() + "线程停止执行");
}
}
结果可能很多种
线程插队
join合并线程,待此线程执行完成后,再执行其他的线程,其他线程阻塞
可以想象成为插队
package state;
/**
* @Classname TestJoin
* @Description TODO
* @Date 2020/12/8 10:10
* @Created by mmz
*/
/*join 想象为插队*/
public class TestJoin implements Runnable{
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("线程vip来了 " +i);
// try {
// Thread.sleep(1000);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
}
}
public static void main(String[] args) {
TestJoin testJoin = new TestJoin();
Thread thread = new Thread(testJoin);
thread.start();
for (int i = 0; i < 500; i++) {
System.out.println("main "+ i);
if( i == 200){
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
这个例子在一开始的时候,因为线程启动了,所以有两个线程,主线程和testjoin两个线程,所以cpu会交替的执行,但是如果main线程执行到200的时候,这个时候会让testjoin线程插队,所以必须等testjoin线程结束之后,才能继续执行主线程
观看线程状态
package state;
/**
* @Classname TestState
* @Description TODO
* @Date 2020/12/8 10:20
* @Created by mmz
*/
/*观察测试线程的状态*/
public class TestState {
public static void main(String[] args) {
Thread thread = new Thread(() -> {
for (int i = 0; i < 5; i++) {
try {
Thread.sleep(1000);
System.out.println("-----");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
// 观察状态
Thread.State state = thread.getState();
System.out.println(state); // new
// 观察启动
thread.start();
state = thread.getState();
System.out.println(state); // 运行
while (state != Thread.State.TERMINATED){ // 只要线程不终止就一直输出状态
try {
Thread.sleep(1000);
state = thread.getState();
System.out.println(state);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
线程的优先级
java提供一个线程调度器来监控程序中启动后进入就绪状态的所有线程,线程调度器按照优先级决定应该调度哪个线程来执行
线程的优先级范围是从1~10
Thread.Min_PRIORTY=1
Thread.Max_PRIORTY=10
Thread.NORM_PRIORTY=5
用一下方法可以改变优先级
getPriority().setPriority(int x);
package state;
/**
* @Classname TestPriority
* @Description TODO
* @Date 2020/12/8 10:30
* @Created by mmz
*/
/*测试线程优先级*/
public class TestPriority extends Thread{
public static void main(String[] args) {
System.out.println(Thread.currentThread().getName() +"-->" +Thread.currentThread().getPriority() );
MyPriority myPriority = new MyPriority();
Thread thread1 = new Thread(myPriority);
Thread thread2 = new Thread(myPriority);
Thread thread3 = new Thread(myPriority);
Thread thread4 = new Thread(myPriority);
Thread thread5 = new Thread(myPriority);
Thread thread6 = new Thread(myPriority);
thread1.start();
thread2.setPriority(1);
thread2.start();
thread3.setPriority(4);
thread3.start();
thread4.setPriority(Thread.MAX_PRIORITY);
thread4.start();
thread5.setPriority(-1);
thread5.start();
thread6.setPriority(11);
thread6.start();
}
}
class MyPriority implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName() +"-->" +Thread.currentThread().getPriority() );
}
}
守护线程
线程分为用户线程和守护线程
虚拟机必须确保用户线程执行完毕
虚拟机不用等待守护线程执行完毕
如:后台记录操作日志,监管内存,垃圾回收
package state;
/**
* @Classname TestDaemon
* @Description TODO
* @Date 2020/12/8 10:50
* @Created by mmz
*/
/*守护线程*/
public class TestDaemon {
public static void main(String[] args) {
God god = new God();
You you = new You();
Thread thread = new Thread(god);
thread.setDaemon(true); // 默认是false,表示用户线程,正常的线程都是用户线程
thread.start(); // 上帝守护线程启动
new Thread(you).start();// 用户线程启动
}
}
class God implements Runnable{
@Override
public void run() {
while (true){
System.out.println("上帝保佑着你");
}
}
}
class You implements Runnable{
@Override
public void run() {
for (int i = 0; i < 36500; i++) {
System.out.println("你一生都开心的或者");
}
System.out.println("goodbye world");
}
}