线程知识点汇总

  1. 线程是不是创建的越多越好?
    首先答案肯定是不是的。在计算机世界里面回答问题不要有绝对性。
    原因具体为以下几点:
    在这里插入图片描述
    在这里插入图片描述
    Thread 中的 State 枚举
 public enum State {
        /**
         * Thread state for a thread which has not yet started.
         * 尚未启动的线程的线程状态
         * 
         * 线程新建,还未调用start方法时。列如 :Thread thread=new Thread(new MyThread());
         */
        NEW,

        /**
         * Thread state for a runnable thread.  A thread in the runnable
         * state is executing in the Java virtual machine but it may
         * be waiting for other resources from the operating system
         * such as processor.
         * 可运行线程的线程状态。可运行的线程 
         * 状态在 Java 虚拟机中执行,但它可能
         * 等待来自操作系统的其他资源 
         * 如处理器
         * 
         * 当调用start()方法后 线程的状态
         * thread.start();
         */
        RUNNABLE,

        /**
         * Thread state for a thread blocked waiting for a monitor lock.
         * A thread in the blocked state is waiting for a monitor lock
         * to enter a synchronized block/method or
         * reenter a synchronized block/method after calling
         * {@link Object#wait() Object.wait}.
         * 
         * 线程阻塞等待监视器锁的线程状态。 
         * 处于阻塞状态的线程正在等待监视器锁 
         * 输入同步块/方法或 
         * 调用后重新进入同步块/方法
         */
        BLOCKED,

        /**
         * Thread state for a waiting thread.
         * A thread is in the waiting state due to calling one of the
         * following methods:
         * <ul>
         *   <li>{@link Object#wait() Object.wait} with no timeout</li>
         *   <li>{@link #join() Thread.join} with no timeout</li>
         *   <li>{@link LockSupport#park() LockSupport.park}</li>
         * </ul>
         *
         * <p>A thread in the waiting state is waiting for another thread to
         * perform a particular action.
         *
         * For example, a thread that has called <tt>Object.wait()</tt>
         * on an object is waiting for another thread to call
         * <tt>Object.notify()</tt> or <tt>Object.notifyAll()</tt> on
         * that object. A thread that has called <tt>Thread.join()</tt>
         * is waiting for a specified thread to terminate.
         */
        WAITING,

        /**
         * Thread state for a waiting thread with a specified waiting time.
         * A thread is in the timed waiting state due to calling one of
         * the following methods with a specified positive waiting time:
         * <ul>
         *   <li>{@link #sleep Thread.sleep}</li>
         *   <li>{@link Object#wait(long) Object.wait} with timeout</li>
         *   <li>{@link #join(long) Thread.join} with timeout</li>
         *   <li>{@link LockSupport#parkNanos LockSupport.parkNanos}</li>
         *   <li>{@link LockSupport#parkUntil LockSupport.parkUntil}</li>
         * </ul>
         * 具有指定等待时间的等待线程的线程状态。
         * 线程由于调用其中之一而处于定时等待状态 
         * 具有指定正等待时间的以下方法
         * 当调用了sleep、wait、join 、LockSupport.parkNanos、LockSupport.parkUntil 等方法时,线程会进入到此状态。
         */
        TIMED_WAITING,

        /**
         * Thread state for a terminated thread.
         * The thread has completed execution.
         */
        TERMINATED;
    }

线程中 join 方法的相关状态

public class ThreadJoin {
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> {
            try {
                Thread.sleep(10000L);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        Thread t2 = new Thread(() -> {
            try {
                System.out.println("t2 中执行t1.join(5000l)");
                t1.join(5000L); // t2 等待 t1 1.5秒
                System.out.println("t2 中执行t1.join()");
                t1.join();// t2 等待 t1 执行完
                System.out.println("t2 执行完成!");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        t1.start();
        t2.start();

        Thread.sleep(1000L);

        System.out.println("t2 状态 "+t2.getState());

        Thread.sleep(5000L);

        System.out.println("t2 状态 "+t2.getState());
    }
}

执行结果

t2 中执行t1.join(5000l)
t2 状态TIMED_WAITING
t2 中执行t1.join()
t2 状态WAITING
t2 执行完成!
public class SynchronizedThread {
    public static void main(String[] args) throws InterruptedException {
        Thread t1=new Thread(()->{
           synchronized (SynchronizedThread.class){
               System.out.println(" t1 抢到锁");
           }
        });

        synchronized (SynchronizedThread.class) {
            t1.start();
            Thread.sleep(1000L);
            System.out.println("t1抢不到锁时候的状态 "+t1.getState());
        }
    }
}

打印结果

t1抢不到锁时候的状态 BLOCKED
 t1 抢到锁

public class ThreadWait {
    public static void main(String[] args) throws InterruptedException {
        Object obj = new Object();
        Thread t1 = new Thread(() -> {
            synchronized (obj) {
                try {
                    System.out.println(" t1将wait ( 3000L)");
                    // wait 方法释放锁,将锁放开,此时 main 线程获取锁
                    obj.wait(3000L);
                    // wait后的代码没有直接执行

                    // 主线程的synchronized 方法中代码执行完毕
                    // 同时使用了 obj.notify() 所以代码执行顺序回到这里
                    System.out.println(" t1将wait()");
                    // 结合上面写的 执行wait 方法后,会释放锁资源,线程的执行顺序又走到了主线程中
                    obj.wait();


                    // 此时如果再次争抢到锁的话,t1的状态就是 RUNNABLE
                    System.out.println(" t1 执行完");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }
        });
        t1.start();
        System.out.println("main <--> t1 start() 后的状态: " + t1.getState()); // timed_waiting

        Thread.sleep(1000L);
        synchronized (obj) {
            // 由于 在线程中使用了wait方法,线程的锁释放,主线程争抢到锁。
            // 因为 wait方法中是有时间参数 所以状态是 TIMED_WAITING 如果没有时间参数的话,就是 WAITING
            System.out.println("main <--> t1的状态: " + t1.getState()); // timed_waiting
            // 唤醒wait()方法
            obj.notify();
            // 休息一秒 但是锁并未释放资源
            Thread.sleep(1000L);
            // ? wating ? blocked

            // 如果 没有上面的  obj.notify() 代码 那么他的状态就是  TIMED_WAITING
            // 为什么时TIMED_WAITING 不是  wating   因为他是定时等待

            // 因为使用了唤醒,但是主线程还是在锁的状态中 所以 t1 的状态是 BLOCKED
            System.out.println("main <-->sleep 1000 后  t1的状态: " + t1.getState());
        }

        Thread.sleep(3000L);
        // 因为 t1 的线程中 使用了 没有时间参数的 wait方法所以 状态是waiting
        System.out.println("main <-->sleep 3000 后 t1的状态:" + t1.getState());

        // 抢到锁以后,对 对象进行 唤醒
        synchronized (obj) {
            obj.notify();
        }
        // 如果线程中 还没有执行完的话,那么此时的线程是 阻塞状态
        System.out.println("main <--> obj.notify()后  t1的状态:" + t1.getState());

        //t1线程执行完毕后 继续执行main 线程的代码
        Thread.sleep(1000L);
        System.out.println("main <--> obj.notify() 然后 sleep 1000L 后 t1的状态:" + t1.getState());


    }

//    打印结果
//    t1将wait ( 3000L)
//main <--> t1的状态: TIMED_WAITING
//main <-->sleep 1000 后  t1的状态: BLOCKED
// t1将wait()
//main <-->sleep 3000 后 t1的状态:WAITING
//main <--> obj.notify()后  t1的状态:BLOCKED
// t1 执行完
//main <--> obj.notify() 然后 sleep 1000L 后 t1的状态:TERMINATED

    // 如果第一开始 wait() 方法没有指定时间,并且 没有唤醒的话,那么就是waiting状态
    // t1将wait ()
    //main <--> t1的状态: WAITING
    //main <-->sleep 1000 后  t1的状态: WAITING
    //main <-->sleep 3000 后 t1的状态:WAITING
    //main <--> obj.notify()后  t1的状态:BLOCKED
    // t1将wait()
    //main <--> obj.notify() 然后 sleep 1000L 后 t1的状态:WAITING
}
public class ThreadPark {
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> {
            LockSupport.park();
        });
        t1.start();
        Thread.sleep(2000L);

        System.out.println("t1.getState() => " + t1.getState());
        // t1.getState() => WAITING
        // LockSupport.park() 和wait 类似都是一种 没有设置时间的线程等待 状态都是 waiting
        // 需要用  LockSupport.unpark(t1) 唤醒

        LockSupport.unpark(t1);
        System.out.println("2000 t1.getState() => " + t1.getState());

    }
}

//t1.getState() => WAITING
public class ThreadIo {

    public static void main(String[] args) throws InterruptedException {
        Charset charset = Charset.forName("UTF-8");
        Thread t1=new Thread(()->{
            try(ServerSocket socket = new ServerSocket(9001)) {
                while (true) {
                    System.out.println(" t1 即将接收连接...");//接收连接
                    Socket s = socket.accept();
                    System.out.println(" t1接收到连接...");
                    BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(s.getInputStream(), charset));
                    String mess=null;
                    System.out.println("t1 将接收连接的数据...");
                    while (StrUtil.isNotEmpty((mess = bufferedReader.readLine()))) {
                        System.out.println("mess => " + mess);
                    }
                    s.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        });

        t1.start();
        Thread.sleep(3000L);
        System.out.println("t1的状态:" + t1.getState());
        Thread.sleep(  20000L);
        System.out.println("t1的状态:" +t1.getState());

    }
}

// 打印结果

为什么Thread.stop() 方法被废除了。

不安全
会立刻释放所有持有的锁,会导致被保护资源不一致,使程序结果不确定

如何正确的停止线程
1.使用violate boolean变量来标识线程是否停止
2.停止线程时,需要调用停止线程的interrupt()方法,因为线程有可能在wait()或sleep(),提高停止线程的即时性
3.对于blocking IO的处理,尽量使用InterruptibleChannel来代替
blocking lO

public class InterruptDemo {
    static volatile boolean flag = true;

    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> {
            while (flag) {

            }
            System.out.println(Thread.currentThread().getName() + " 执行 interrupted 的返回" + Thread.interrupted());

            while (!flag) {

            }
        });

        t1.start();
        Thread.sleep(100L);
        System.out.println("interrupt() 前的状态: " + t1.isInterrupted());
        System.out.println("执行interrupt()");
        t1.interrupt();
        System.out.println("interrupt()后的状态: " + t1.isInterrupted());
        System.out.println("设置f1ag=false");
        flag=false;
        Thread.sleep(100L);
        System.out.println("从main中再次获取t1的中断状态: " + t1.isInterrupted());
        flag=true;

        Thread t2=new Thread(()->{
            System.out.println("t2 sleep 2000L");
            try {
                Thread.sleep(2000L);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("t2中获取自己的中断状态: " + Thread.currentThread( ).isInterrupted());

        });
        t2.start();
        Thread.sleep(100L);
        System.out.println("从main中断t2 ");
        t2.interrupt();

    }
}
// 打印结果
//interrupt() 前的状态: false
//执行interrupt()
//interrupt()后的状态: true
//设置f1ag=false
//Thread-0 执行 interrupted 的返回true
//从main中再次获取t1的中断状态: false
//t2 sleep 2000L
//从main中断t2 
//t2中获取自己的中断状态: false
//java.lang.InterruptedException: sleep interrupted

上述代码的逻辑 ,在main线程中调用了 t1.interrupt(); 方法后,在线程内部自己获取判断是否 已经是已中断

 System.out.println(Thread.currentThread().getName() + " 执行 interrupted 的返回" + Thread.interrupted()); 

Thread.interrupted() 返回的结果是 true 。然后再次在main线程中获取 t1.isInterrupted() 发现 状态又变回了false , 说明在 线程内部的 Thread.interrupted() 方法中擦除了 线程的中断标识。 其意义是,线程内部已经收到了,线程的被中断了,下一次,其他线程又可以继续中断他了。

//t2 sleep 2000L
//从main中断t2
//t2中获取自己的中断状态: false
结合这几行输出结果 对应的代码 ,可以看到

  Thread t2=new Thread(()->{
            System.out.println("t2 sleep 2000L");
            try {
                Thread.sleep(2000L);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("t2中获取自己的中断状态: " + Thread.currentThread( ).isInterrupted());

        });
        t2.start();
        Thread.sleep(100L);
        System.out.println("从main中断t2 ");
        t2.interrupt();

在线程中的sleep的时候,线程的状态是TIME_WAITING 或者WAITING ,此时,如果在main线程中断了线程,那么被sleep的catch 捕捉到 中断异常,那么在线程中打印Thread.currentThread( ).isInterrupted() 就会提示false;因为已经拦截到中断异常了,所以不用再去线程中设置中断标识。

总结: 如果线程是RUNABLE 状态 ,在外面设置了线程的t2.interrupt() 方法,那么在线程内部是可以获取到 isInterrupted() 等于true ,同时擦除,如果是WAITING或者TIME_WAITING 状态,调用 t2.interrupt() 方法,则会抛出中断异常且 不会获取到中断状态标识 等于 true

public class StopDemo {
    public static void main(String[] args) throws InterruptedException {
        final  Object object=new Object();

        try {
            Thread t1 = new Thread(){
                @Override
                public void run() {
                    synchronized (object){
                        System.out.println(getName()+" 抢到锁了");
                        try {
                           sleep(3000);
                        } catch (InterruptedException e) {
                            System.out.println("sleep异常");
                        }
                        System.out.println(Thread.currentThread().getName()+" 释放锁了");
                    }
                }
            };
            Thread t2=  new Thread(){
                @Override
                public void run() {
                    synchronized (object){
                        System.out.println(getName()+" 获取到锁了 ");
                    }
                }
            };


            t1.start();
            Thread.sleep(100L);
            t2.start();
            t1.stop();
        } catch (Exception e) {
            System.out.println("main "+e.getMessage());
        }

    }
}
// 打印结果
// Thread-0 抢到锁了
// Thread-1 获取到锁了 

使用上述StopDemo 代码,查看执行结果是 同时打印了两句获取到锁的语句,按照正常逻辑,应该是Thread-0 先获取锁,再释放锁,然后Thread-1 再获取锁,因为t0 直接调用了stop()方法,同时释放了所有的锁资源,所以,t2 同时抢到锁了。这也是为什么stop方法被废除的主要原因。

线程池任务数量的统计在这里插入图片描述

  • 10
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值