zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    『转』 PreTranslateMessage作用和使用方法
    either...or...与 neither...nor...
    CSS五類常用選擇器(收藏)
    JQuery选择器(selectors 的xpath语法应用)
    我是怎么看friends练口语的(转贴)
    变量的命名方法【Hungarian】【camelCase】【PascalCase】
    JavaScript继承机制的实现(未完)
    JavaScript面向对象编程(1) 基础
    Javascript:Object.extend
    JavaScript面向对象编程(2) 类的定义
  • 原文地址:https://www.cnblogs.com/erdanyang/p/11381048.html
Copyright © 2011-2022 走看看