线程终止的方法
1、join(方法)
join()方法,其实是线程间通信的一种方法
如果在主线程中调用该方法,会让主线程休眠,
让调用该方法的线程执行完毕后再恢复执行主线程
从运行态到阻塞态 join(),会释放对象锁
阻塞态到就绪态 join()线程执行完毕
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
class MyThread implements Runnable{
@Override
public void run() {
for(int i=0;i<3;i++){
System.out.println(Thread.currentThread().getName()+"、"+i);
}
}
}
public class Test {
public static void main(String[] args) {
System.out.println("main线程开始");
MyThread myThread=new MyThread();
new Thread(myThread,"子线程A").start();
System.out.println("main线程结束");
}
public static void PrintTime(){
Date date=new Date();
DateFormat dateFormat=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String str=dateFormat.format(date);
System.out.println(str);
}
}
运行结果:
在我们进行调用join()方法之前,我们发现,主线程,子线程,自己调用自己的线程
join方法只是对于object提供的wait()做了一层封装。
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
class MyThread implements Runnable{
@Override
public void run() {
System.out.println("主线程休眠开始...." );
Test.PrintTime();
try {
Thread.sleep(3000);
}catch (InterruptedException e){
e.printStackTrace();
}
System.out.println("主线程休眠结束....");
Test.PrintTime();
}
}
public class Test {
public static void main(String[] args)throws InterruptedException {
System.out.println("main线程开始");
MyThread myThread=new MyThread();
Thread thread= new Thread(myThread,"子线程A");
thread.start();
thread.join();
thread.sleep(2000);
System.out.println("main线程结束");
}
public static void PrintTime(){
Date date=new Date();
DateFormat dateFormat=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String str=dateFormat.format(date);
System.out.println(str);
}
}
运行结果:
我们可以发现,在执行join方法之后,我们的主线程开始停止运行,先执行我们的子线程。
public final synchronized void join(long millis)
throws InterruptedException {
long base = System.currentTimeMillis();
long now = 0;
if (millis < 0) {
throw new IllegalArgumentException("timeout value is negative");
}
if (millis == 0) {
while (isAlive()) {
wait(0);
}
} else {
while (isAlive()) {
long delay = millis - now;
if (delay <= 0) {
break;
}
wait(delay);
now = System.currentTimeMillis() - base;
}
}
}
这是实现join方法的一段源码,我们可以可以看到join()方法的本质只是一种对于wait方法的封装。
线程停止的方法
1、设置标志位停止线程
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
class MyThread implements Runnable{
private boolean flag=true;
@Override
public void run() {
int i=1;
while(flag){
System.out.println(Thread.currentThread().getName()+"第"+i+"次执行。。。");
try{
Thread.sleep(1000);
}catch (InterruptedException e){
e.printStackTrace();
}
i++;
}
}
public void setFlag(boolean flag){
this.flag=flag;
}
}
public class Test {
public static void main(String[] args)throws InterruptedException {
MyThread mt=new MyThread();
Thread thread=new Thread(mt,"A");
thread.start();
thread.sleep(5000);
mt.setFlag(false);
}
}
运行结果:
- 我们可以看到,我们通过设置标志位,我们可以清晰地看见在我们主线程等待5秒的时间里面,
- 我们的子线程每次运行只等待1秒,所以的子线程在等待子线程的过程中,我们的子线程运行了5次。
- 5秒之后,由于我们的在主线程中将子线程设置的标志位改变,所以我们的子线程退出。
**
2、调用stop方法
**
调用stop方法强制停止线程,该方法不安全,已经被Deprecated
这种停止方式很同意产生我们的废弃数据
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
class MyThread implements Runnable{
private boolean flag=true;
@Override
public void run() {
int i=1;
while(flag){
System.out.println(Thread.currentThread().getName()+"第"+i+"次执行。。。");
try{
Thread.sleep(1000);
}catch (InterruptedException e){
e.printStackTrace();
}
i++;
}
}
}
public class Test {
public static void main(String[] args)throws InterruptedException {
MyThread mt=new MyThread();
Thread thread=new Thread(mt,"A");
thread.start();
thread.sleep(5000);
thread.stop();
}
}
运行结果:
stop方法不安全在一旦调用它,它一旦执行,那我们调用它的线程会立马退出,那么很有可能产生垃圾数据。
3、调用Thread类的Interrupt()方法(能用不好理解)
interrupt()方法只是将线程状态置为中断状态而已,它不会中断一个正在运行的线程。此方法只是在给线程传递一个中断的限号,程序可以根据此信号来判断是否需要终止。是否要终止取决于程序中的处理。
这个标志位是系统帮助我们设置的
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
class MyThread implements Runnable{
@Override
public void run() {
int i = 1;
while (true) {
boolean flag=Thread.currentThread().isInterrupted();
System.out.println(Thread.currentThread().getName() + "第" + i + "次执行。。。");
System.out.println(flag);
i++;
if(flag){
System.out.println("线程退出");
break;
}
}
}
}
public class Test {
public static void main(String[] args)throws InterruptedException {
MyThread mt=new MyThread();
Thread thread=new Thread(mt,"A");
thread.start();
thread.sleep(3000);
thread.interrupt();
}
}
当线程中使用wait 、sleep、join三个方法引起的阻塞,那么会将线程的中断标志重新设置false,并抛出一个InterruptedException;
并且将线程的中断状态由true置为false。
我们要知道,我们的interrupt只是将我们的状态改变,并不会将线程退出,如果要将线程退出,我们要做的就是将在线程中断标志改变之后,所改变后的状态要如何处理。