黑马程序员:Java基础 您所在的位置:网站首页 进程关闭线程会结束吗 黑马程序员:Java基础

黑马程序员:Java基础

#黑马程序员:Java基础| 来源: 网络整理| 查看: 265

------- Java EE培训、 java培训、期待与您交流! ---------- 1.概念

线程启动了,做完该做的事情,但是它还是会占用系统资源,那么我们该如何停止呢?

我们知道Java中Thread里面有一个方法叫做stop方法,可是,stop方法已经过时。

那么,如何停止线程?只有一种,run方法结束。

开启多线程运行,运行代码通常是循环结构。只要控制住循环,就可以让run方法结束,也就是线程结束。

我们先来举个例子:

class StopThread implements Runnable{private Boolean flag = true;public void run(){while(flag){System.out.println(Thread.currentThread().getName()+"---run");}}public void changeFlag(){flag = false;}}

public class StopThreadDemo { public static void main(String[] args) { StopThread sThread = new StopThread();

new Thread(sThread).start(); new Thread(sThread).start();

int num = 0; while(true){ if(num++ == 60){ sThread.changeFlag(); break; } System.out.println(Thread.currentThread().getName()+"++++++"+num); } System.out.println("Over"); }}

我们来看一下运行结果:

只见这哥们一顿运行,到了num==60的时候程序调用了changeFlag()结束了所有线程。

有一种特殊情况,这种情况程序停不下来,那就是使用了synchronized的同步锁。

我们先来看一下代码:

class StopThread implements Runnable{private Boolean flag = true;public synchronized void run(){while(flag){try {wait();} catch (InterruptedException e) {e.printStackTrace();System.out.println(Thread.currentThread().getName()+"...Exception");}System.out.println(Thread.currentThread().getName()+"---run");}}public void changeFlag(){flag = false;}}

public class StopThreadDemo { public static void main(String[] args) { StopThread sThread = new StopThread();

new Thread(sThread).start(); new Thread(sThread).start();

int num = 0; while(true){ if(num++ == 60){ sThread.changeFlag(); break; } System.out.println(Thread.currentThread().getName()+"++++++"+num); } System.out.println("Over"); }}

接下来,我们来运行一下:

可以看到,我们的程序只有main线程在输出,而其他两个线程则没有动静,而且,注意图的右上角,红色的小方块证明了这个程序还没有结束。这是为什么呢?

我们回顾一下代码:

我们的flag默认为true,当线程进入synchronized同步锁中判断flag就会直接被位于上面的wait()方法直接叫停,也就是进入冻结状态,同时释放了CPU运行权。这是另一个线程也来了,同样被wait()方法叫停。这两个方法一旦被叫停就无法读取到位于wait()下面的标记,也就无法终止线程了。

我们这样总结:

当线程处于冻结状态时就不会读取到标记,那么线程就不会结束。

那么该如何解决这个问题呢?

在Java的Thread中提供了一种中断线程的方法——interrupt,需要注意的是这个中断不是停止线程,能停止线程的只有stop方法。

* 如果线程在调用Object 类的wait()、wait(long) 或wait(long, int) 方法,或者该类的join()、join(long)、join(long, int)、sleep(long) 或sleep(long, int) 方法过程中受阻,则其中断状态将被清除

interrupt方法的意思就是强制清除线程的冻结状态,即强制唤醒。但是会将收到一个InterruptedException异常。

我们来修改一下代码:

class StopThread implements Runnable{private Boolean flag = true;public synchronized void run(){while(flag){try {wait();} catch (InterruptedException e) {e.printStackTrace();System.out.println(Thread.currentThread().getName()+"...Exception");}System.out.println(Thread.currentThread().getName()+"---run");}}public void changeFlag(){flag = false;}}

public class StopThreadDemo { public static void main(String[] args) { StopThread sThread = new StopThread();

Thread t1 = new Thread(sThread); t1.start(); new Thread(sThread).start();

int num = 0; while(true){ if(num++ == 60){ //sThread.changeFlag(); t1.interrupt(); break; } System.out.println(Thread.currentThread().getName()+"++++++"+num); } System.out.println("Over"); }}

然后我们运行一下:

注意图中,线程没有终止,而且接收到了异常。为什么没有终止?因为t1被强制唤醒以后又去争CPU执行权时,经过wait()方法时,又一次冻结在那里。同理,另一条线程也这样修改。

这时,我们离结束线程不远了,只要发生了异常我们不妨操作标记来结束线程:

class StopThread implements Runnable{private Boolean flag = true;public synchronized void run(){while(flag){try {wait();} catch (InterruptedException e) {e.printStackTrace();System.out.println(Thread.currentThread().getName()+"...Exception");flag = false;}System.out.println(Thread.currentThread().getName()+"---run");}}public void changeFlag(){flag = false;}}

public class StopThreadDemo { public static void main(String[] args) { StopThread sThread = new StopThread();

Thread t1 = new Thread(sThread); t1.start(); Thread t2 = new Thread(sThread); t2.start();

int num = 0; while(true){ if(num++ == 60){ //sThread.changeFlag(); t1.interrupt(); t2.interrupt(); break; } System.out.println(Thread.currentThread().getName()+"++++++"+num); } System.out.println("Over"); }}

运行结果如下:

我们可以看到,线程异常一样是被输出,但是注意右上角,小方块呈灰色,证明此时程序已经停止运行,也就是说,我们已经将t1,t2两个线程成功的终止掉了。

2.守护线程

Java中提供了一种方法——setDaemon()

setDaemon()将该线程标记为守护线程或用户线程。当正在运行的线程都是守护线程时,Java 虚拟机退出。

守护线程可以理解为后台线程。

该方法必须在启动线程前调用。

该方法首先调用该线程的 checkAccess 方法,且不带任何参数。这可能抛出 SecurityException(在当前线程中)。

接下来我们看一下示例:

class DaemonThread implements Runnable {private Boolean flag = true;

public void run() {while (flag) {System.out.println(Thread.currentThread().getName() + "---run");}}

public void changeFlag() {flag = false;}}

public class DaemonDemo {public static void main(String[] args) {StopThread sThread = new StopThread();

Thread t1 = new Thread(sThread);Thread t2 = new Thread(sThread);

t1.setDaemon(true);t2.setDaemon(true);t1.start();t2.start();

int num = 0;while (true) {if (num++ == 60) {break;}System.out.println(Thread.currentThread().getName() + "++++++" + num);}System.out.println("Over");}}

运行结果是main方法做完了应有的工作,而此时程序关闭。

3.Join()方法

前面Interrupt()方法中我们见到过join()方法,join()是什么呢?

接下来我们来看一下join()方法:

在JDK中是这么说的:等待该线程终止。

我们不妨先来看段代码:

class Join implements Runnable{public void run(){for(int i = 0;iSystem.out.println(Thread.currentThread().getName()+"---"+i);}}}

public class JoinDemo { public static void main(String[] args) throws InterruptedException {Join j = new Join();Thread t1 = new Thread(j);Thread t2 = new Thread(j);

t1.start();t1.join(); //join是抢夺CPU执行权t2.start();

for(int i=0;iSystem.out.println("main______"+i);}System.out.println("Over!!!");}}

运行结果:通常情况下,我们的t1,t2,main线程都是交叉运行,输出结果的。但是,当我们添加join()方法后,如上面的代码,这个程序输出的顺序就会是这样的:

1.先让t1全部执行完。

2.再让t2和main线程交替运行。

3.执行完毕,最后关闭程序。

我们就可以理解了,join()方法是一个让本线程执行完,再让其他线程执行的方法。

可是接下来我们这样改:

t1.start();t2.start();t1.join(); 我把join()放到了t2.start()后面去,执行结果如下:

这又是怎么回事呢?

当A线程执行到了B线程的.join()方法时,A就会等待,等B线程都执行完,A才会执行。

join可以用来临时加入线程执行。

但是当A线程启动,B线程也会启动,但是当主线程碰到A线程的join方法时,主线程就会进入等待状态,而此时A,B线程都在运行状态,那么这时A,B线程就会交替执行,执行完后主线程就会执行。但是,此时的A,B线程并没有消亡,而是处于挂起状态,当主线程执行完毕后才会一起结束,此时,程序结束。

4.优先级&yield方法

        优先级代表抢资源的频率。

     优先级有10级

     其中1,5,10级为最明显。

static int

MAX_PRIORITY       线程可以具有的最高优先级。

static int

MIN_PRIORITY       线程可以具有的最低优先级。

static int

NORM_PRIORITY       分配给线程的默认优先级。



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有