java的线程池的基础类

一、java线程基础知识

进程是操作系统分配资源的基本单位

线程是cpu调度的基本单位

jdk线程是协作式的不是抢占式的,操作系统线程是抢占式的

死锁不理会中断

synchronized等待不可以被中断,代码可以被中断

1、停止线程的方法:

1、这四个方法已被废弃

      stop()(强行停止线程)

      destroy()

      resume()

      suspend()(挂起一个线程,但是不释放琐资源)

2、interrup()将中断标志位置为true

     isInterrupted() 判断中断标志是否为true

  static方法interrupted()判断中断标志是否为true;如果中断标志为true,并且将中断标志位置为false

    sleep,wait,join方法被中断后,后会出现抛出InterruptException异常的情况

 reentrantLock.lockInterruptibly();

 当线程抛出InterruptException异常以后,中断标志位会被复位。

特别注意的是需要在InterruptException的catch语句里添加Thread.currentThread().interrupt();进行再次中断,否则会出现死循环的现象。

public class Main {
    public static void main(String[] args) throws Exception {
        Thread t = new Thread(new Runnable() {

            @Override
            public void run() {
                // TODO Auto-generated method stub
                while (!Thread.currentThread().isInterrupted()) {
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        System.out.println("1、" + Thread.currentThread().isInterrupted());
                        Thread.currentThread().interrupt();
                        e.printStackTrace();
                    }
                    System.out.println("2、" + Thread.currentThread().isInterrupted());
                }
                System.out.println("3、" + Thread.currentThread().isInterrupted());

            }
        });
        t.start();
        Thread.sleep(500);
        t.interrupt();
    }

}

 

2、创建线程的方法

Thread,Runnable,Callable

thread的start方法只可以执行一次;run方法可以执行多次。

利用Callable创建线程的方法:

import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;

public class Main {
    public static void main(String[] args) throws Exception {
        FutureTask<String> futureTask = new FutureTask<String>(new Callable<String>() {

            @Override
            public String call() throws Exception {
                // TODO Auto-generated method stub
                System.out.println("callable!");
                return "callableResult";
            }
        });
        new Thread(futureTask).start();
        System.out.println(futureTask.get());
    }

}

 3、守护线程与非守护线程

  main主线程结束,子线程仍会继续运行。

  只有当所有的非守护线程都运行结束,jvm才会退出。

  守护线程的finally语句是不能保证执行的。用户线程finally一定会执行。

 4、线程的其他方法

  yield()线程主动让出cpu执行权;将线程从运行状态到就绪状态

  线程优先级为1~10,默认值为5

  yield()与sleep():执行yield方法后线程到就绪状态,执行sleep方法后线程没有到就绪状态

  join()方法

 5、线程间的协同机制

  (1)synchronized内置锁(对象锁和类锁)【本质就是对象锁,对象头里的标志】

    对象锁和类锁之间是相互独立的,相互之间是不干扰的

    类锁锁的是Class对象

    类锁和静态变量的锁是可以并行的,因为他们锁的不是同一个对象

    synchronized的本质就是锁对象

    System.identityHashCode(Object x)返回对象原生的HashCode

  (2)volatile

    只有一个线程写, 其它线程读的场景。

  (3)ThreadLocal

    多线程环境下可以随意使用

    定义成private static

    为每一个线程都提供了变量的副本

    线程池的时候使用ThreadLocal

    spring的事务处理有用到(保证是在同一个连接里)把这个连接绑定到threadlocal里面

    ThreadlLocal弱引用

    ThreadLocal就是一个变量的包装类,可以这样子理解

    ThreadLocal最好用private static修饰

    Thread---->ThreadLocalMap---->Entry(Threadlocal1,value1)

                  ---->Entry(Threadlocal2,value2)

                  ---->Entry(Threadlocal3,value3)

    ThreadLocalMap的底层是一个Entry数组,使用hash表插入,用开放寻址法解决冲突问题

  (4)wait()/notify()/notifyAll()/wait(1000ms)

    这些方法都是Object的方法

 (5)join()方法【可以实现线程串联排队执行】保证两个线程顺序的执行

    怎么保证一个线程在另一个线程之前执行完?join(),countDownLatch()

 (6)锁的机制:yield()方法,交出cpu执行权,但是不释放锁

        sleep()方法,交出cpu执行权,但是不释放锁

       wait()方法之前必须持有锁,方法之后必须释放锁,当wait()方法返回的时候,线程必须重新持有锁

       notify()方法之前必须持有锁,方法之后同步代码块执行完才会释放锁

wait/notify标准范式

        //通知
        synchronized (对象) {
            while(条件不满足) {
                对象.wait();
            }
            //业务逻辑
        }
        //等待
        synchronized (对象) {
            //业务逻辑,改变条件
            对象.notify()/notifyAll()
        }
                    

 

1、中断机制

如果线程堵塞在object.wait、Thread.join和Thread.sleep,将会清除线程的中断状态,并抛出InterruptedException;

如果线程堵塞在java.nio.channels.InterruptibleChannel的IO上,Channel将会被关闭,线程被置为中断状态,并抛出java.nio.channels.ClosedByInterruptException;

如果线程堵塞在java.nio.channels.Selector上,线程被置为中断状态,select方法会马上返回,类似调用wakeup的效果;

如果不是以上三种情况,thread.interrupt()方法仅仅是设置线程的中断状态为true。

2、中断标志位的设置

Thread.interrupt();只是改变线程的中断状态。

object.wait、Thread.join和Thread.sleep这三个状态下的线程才会不停的检测中断标志,其他状态下的线程是不会检测中断标志的。

一、ThreadPoolExecutor

posted @ 2019-08-20 09:24  海平面下的我们  阅读(186)  评论(0编辑  收藏  举报