• Java Thread part 2


    线程的四种状态

    1. 新建(new) : 在一个线程新建时会短暂的处于这种状态,之后调度器可以将其转为就绪或阻塞

    2. 就绪(runnable) : 这种状态下,线程在任意时间可以运行,也可以不运行

    3. 阻塞(blocked) : 这种状态下,线程被阻止运行。只有当其重新进入就绪状态才能继续运行

    4. 死亡(dead) : 线程不再可调度

    进入阻塞状态的原因

    1. sleep() 方法的调用

    2. Object类的wait()方法的调用,直到收到notify()或notifyAll()的消息

    3. 线程任务在等待输入

    4. 在调用同步方法而对象锁不可用时

    下面是一个阻塞线程的中断例子

    package threadtest2;
    
    import java.util.concurrent.TimeUnit;
    
    public class SleepBlocked extends Thread {
        /**
         * 进入一秒的睡眠阻塞
         */
        @Override
        public void run() {
            try {
                TimeUnit.MILLISECONDS.sleep(1000);
            } catch (InterruptedException e) {
                System.out.println("Sleep blocked has been interrupted");
            }
        }
    }
    
    package threadtest2;
    
    import java.io.IOException;
    import java.io.InputStream;
    
    public class IOBlocked extends Thread {
        InputStream in;
        
        public IOBlocked(InputStream is) {
            this.in = is;
        }
    
        /**
         * 等待输入进入IO阻塞
         */
        @Override
        public void run() {
            System.out.println("Waiting for read");
            try {
                in.read();
            } catch (IOException e) {
                if (Thread.currentThread().isInterrupted()) {
                    System.out.println("IOBlock is interrupted");
                } else {
                    throw new RuntimeException(e);
                }
            }
            System.out.println("Exiting IOBlocked.run()");
        }
    }
    
    package threadtest2;
    
    public class SyncBlocked extends Thread {
        /**
         * 线程构造方法内即调用f()
         */
        public SyncBlocked() {
            (new Thread() {
                @Override
                public void run() {
                    f();
                }
            }).start();
        }
        
        /**
         * 永不释放的锁方法
         */
        public synchronized void f() {
            while (true);
        }
        
        /**
         * 调用f()时进入阻塞
         */
        @Override
        public void run() {
            System.out.println("Trying to call f()");
            f();
            System.out.println("Exiting SyncBlocked.run()");
        }
    }
    
    package threadtest2;
    
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.Future;
    import java.util.concurrent.TimeUnit;
    
    public class Interrupting {
        private static ExecutorService exec =
                Executors.newCachedThreadPool();
        private 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);    // 通过Future的cancel()方法中断线程运行,和interrupt()效果一致
            System.out.println("Interrupt signal sent to " + r.getClass().getName());
        }
        
        /**
         * 最后的输出证明sleep阻塞可以被中断
         * 而IO和Sync的阻塞不可被中断
         * @param args
         * @throws Exception
         */
        public static void main(String[] args) throws Exception {
            test(new SleepBlocked());
            test(new IOBlocked(System.in));
            test(new SyncBlocked());
            TimeUnit.SECONDS.sleep(3);
            System.out.println("Aborting with System.exit(0)");
            System.exit(0);
        }
    }

    1) 通过关闭使用资源来中止阻塞

    package threadtest2;
    
    import java.io.InputStream;
    import java.net.ServerSocket;
    import java.net.Socket;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.TimeUnit;
    
    public class CloseResource {
        public static void main(String[] args) throws Exception {
            ExecutorService exec = Executors.newCachedThreadPool();
            ServerSocket ss = new ServerSocket(8080);
            InputStream socketInput = 
                    new Socket("localhost", 8080).getInputStream();
            exec.execute(new IOBlocked(socketInput));
            exec.execute(new IOBlocked(System.in));
            TimeUnit.MILLISECONDS.sleep(100);
            System.out.println("Shutting down all threads");
            exec.shutdownNow();    // 至此所有线程是不能关闭的
            TimeUnit.SECONDS.sleep(1);
            System.out.println("Closing " + socketInput.getClass().getName());
            socketInput.close();    // 只有当正在使用的资源关闭后才能关闭线程
            TimeUnit.SECONDS.sleep(1);
            System.out.println("Closing " + System.in.getClass().getName());
            System.in.close();
        }
    }

    Waiting for read
    Waiting for read
    Shutting down all threads
    Closing java.net.SocketInputStream
    IOBlock is interrupted
    Exiting IOBlocked.run()
    Closing java.io.BufferedInputStream

    IOBlock is interrupted
    Exiting IOBlocked.run()

    2) 通过使用NIO来响应阻塞的IO线程的中断请求

    package threadtest2;
    
    import java.io.IOException;
    import java.nio.ByteBuffer;
    import java.nio.channels.AsynchronousCloseException;
    import java.nio.channels.ClosedByInterruptException;
    import java.nio.channels.SocketChannel;
    
    public class NIOBlocked extends Thread {
        private final SocketChannel sc;
        public NIOBlocked(SocketChannel sc) { this.sc = sc; }
        @Override
        public void run() {
            System.out.println("Waiting for read in " + this);
            try {
                sc.read(ByteBuffer.allocate(1));
            } catch (ClosedByInterruptException e) {
                // 一个通过interrupt()或者cancel()来中断阻塞的异常
                System.out.println("ClosedByInterruptException accured");
            } catch (AsynchronousCloseException e) {
                // 一个通过关闭正在使用的资源中断阻塞的异常
                System.out.println("AsynchronousCloseException accured");
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
            System.out.println("Exiting NIOBlocked.run() " + this);
        }
    }
    
    package threadtest2;
    
    import java.io.IOException;
    import java.net.InetSocketAddress;
    import java.net.ServerSocket;
    import java.nio.channels.SocketChannel;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.Future;
    import java.util.concurrent.TimeUnit;
    
    public class NIOInterrupting {
        public static void main(String[] args) throws Exception {
            ExecutorService exec = Executors.newCachedThreadPool();
            ServerSocket ss = new ServerSocket(8080);
            InetSocketAddress isa =
                    new InetSocketAddress("localhost", 8080);
            SocketChannel sc1 = SocketChannel.open(isa);
            SocketChannel sc2 = SocketChannel.open(isa);
            Future<?> f = exec.submit(new NIOBlocked(sc1));
            exec.execute(new NIOBlocked(sc2));
            exec.shutdown();
            TimeUnit.SECONDS.sleep(1);
            f.cancel(true);    // 使用NIO可以直接cancel掉阻塞的thread
            TimeUnit.SECONDS.sleep(1);
            sc2.close();    // 也可以通过close正在使用的资源来
        }
    }

    Waiting for read in Thread[Thread-0,5,main]
    Waiting for read in Thread[Thread-1,5,main]
    ClosedByInterruptException accured
    Exiting NIOBlocked.run() Thread[Thread-0,5,main]
    AsynchronousCloseException accured
    Exiting NIOBlocked.run() Thread[Thread-1,5,main]

    一个可以被中断的锁

    package threadtest2;
    
    import java.util.concurrent.TimeUnit;
    import java.util.concurrent.locks.ReentrantLock;
    
    public class LockBlocked extends Thread {
        ReentrantLock lock = new ReentrantLock();
        
        public LockBlocked() {
            lock.lock();
        }
        
        @Override
        public void run() {
            System.out.println("Waiting for lock");
            try {
                // 这是一个可以被interrupt打断的锁
                lock.lockInterruptibly();
            } catch (InterruptedException e) {
                System.out.println("Interrupted from LockBlocked.run()");
            }
            System.out.println("Broken out of constructor lock");
        }
        
        public static void main(String[] args) throws InterruptedException {
            Thread t = new LockBlocked();
            t.start();
            TimeUnit.SECONDS.sleep(2);
            t.interrupt();
        }
    }

    Waiting for lock
    Interrupted from LockBlocked.run()
    Broken out of constructor lock

  • 相关阅读:
    Linux 系统下10个查看网络与监听的命令
    Linux下用gdb 调试、查看代码堆栈
    GPIO引脚速度的应用匹配
    编写安全的代码——小心有符号数的右移操作
    C语言实现类似C++的容器vector
    求字符串长度之递归与非递归的C语言实现
    字符串拷贝函数递归与非递归的C语言实现
    WriteLogHelper
    JsonHelper
    ConfigHelper
  • 原文地址:https://www.cnblogs.com/zemliu/p/2941403.html
Copyright © 2020-2023  润新知