JAVA并发终结任务

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JAVA并发终结任务相关的知识,希望对你有一定的参考价值。

线程状态

新建状态

线程被创建时,会短暂的处于这种状态。处于这种状态的线程已经分配了必须的系统资源,有资格获得cpu时间了,等待调度器把它转变为可运行状态或阻塞状态;

就绪状态

在这种状态下,只要调度器把时间片分配给线程,就可以马上运行;

阻塞状态

线程因为某个条件未满足,阻止了它的运行;这种状态会被调度器忽略,直到条件满足时,转为就绪状态;

死亡状态

线程运行结束或被中断后的状态;该状态不能被调度,不会分配cpu时间;

线程进入阻塞状态的方式

  • 调用sleep方法
  • 调用wait方法
  • 任务等待某个输入输出完成
  • 调用其它同步控制方法,等待其它线程释放锁

线程中断

线程阻塞及中断

先看一段代码,如下:

技术分享
package concurrency;

import java.util.concurrent.*;
import java.io.*;

class SleepBlocked implements Runnable {
    public void run() {
        try {
            TimeUnit.SECONDS.sleep(100);
        } catch (InterruptedException e) {
            System.out.println("InterruptedException");
        }
        System.out.println("Exiting SleepBlocked.run()");
    }
}

class IOBlocked implements Runnable {
    private InputStream in;

    public IOBlocked(InputStream is) {
        in = is;
    }

    public void run() {
        try {
            System.out.println("Waiting for read():");
            in.read();
        } catch (IOException e) {
            if (Thread.currentThread().isInterrupted()) {
                System.out.println("Interrupted from blocked I/O");
            } else {
                throw new RuntimeException(e);
            }
        }
        System.out.println("Exiting IOBlocked.run()");
    }
}

class SynchronizedBlocked implements Runnable {
    public synchronized void f() {
        while (true) // Never releases lock
            Thread.yield();
    }

    public SynchronizedBlocked() {
        new Thread() {
            public void run() {
                f(); // Lock acquired by this thread
            }
        }.start();
    }

    public void run() {
        System.out.println("Trying to call f()");
        f();
        System.out.println("Exiting SynchronizedBlocked.run()");
    }
}

public class Interrupting {
    private static ExecutorService exec = Executors.newCachedThreadPool();

    static void test(Runnable r) throws InterruptedException {
        Future<?> f = exec.submit(r);
        TimeUnit.MILLISECONDS.sleep(100);
        System.out.println("Interrupting " + r.getClass().getName());
        f.cancel(true); // Interrupts if running
        System.out.println("Interrupt sent to " + r.getClass().getName());
    }

    public static void main(String[] args) throws Exception {
        test(new SleepBlocked());
        test(new IOBlocked(System.in));
        test(new SynchronizedBlocked());
        TimeUnit.SECONDS.sleep(3);
        System.out.println("Aborting with System.exit(0)");
        System.exit(0); // ... since last 2 interrupts failed
    }
} 
View Code

以上代码中,展示了三种进入阻塞状态的情景:调用sleep方法,等待io,等待其它线程释放锁;

以及尝试调用Future的cancel方法去中断阻塞的线程,从运行结果可以发现,只有sleep可以被中断,其它等待io和等待锁释放都不能被中断;这一点也可以从sleep方法会抛出InterruptedException异常看出来,其它两个不会抛出该异常;

那么对于io阻塞和互斥锁阻塞的线程如何中断?

中断io阻塞

方式一,调用shutdownNow关闭线程池,调用close方法关闭IO流资源;

方式二,使用nio

中断互斥锁阻塞

使用并发库中的ReentrantLock锁;

ps:如果是同一个线程的话,是可以调用在同一个对象中的其它synchronized方法;

检查中断

调用Thread.interrupted(),查看interrupt()是否调用过,并清除中断状态,避免中断被通知两次;

 

以上是关于JAVA并发终结任务的主要内容,如果未能解决你的问题,请参考以下文章

Java并发系列终结篇:彻底搞懂Java线程池的工作原理

Java 并发编程:线程间的协作(wait/notify/sleep/yield/join)

一个bug在redmine中的诞生到终结

Java并发系列终结篇:学校门口保安小王,这次彻底搞懂了Java线程池的工作原理

java并发编程终结者-思维导图模式

java 并发---Thread 线程