Java多线程API、线程池

Object类相关api(相关的方法一定是当前线程在获取了对应的锁对象才能调用,否则会抛出异常)

  • o.wait() :锁对象调用该方法使当前线程进入等待状态,并立刻释放锁对象,直到被其他线程唤醒进入等锁池。
  • o.wait(long) :锁对象调用该方法使当前线程进入等待状态,同时释放锁对象。但是超过等待的时间后线程会自动唤醒,或者被其他线程唤醒,并进入等锁池中。
  • o.wait(long,int) :和o.wait(long)方法一样,如果int参数大于0则前面的long数字加1
  • o.notify():随机唤醒一个处于等待中的线程(同一个等待阻塞池中)
  • o.notifyAll():唤醒所有等待中的线程(同一个等待阻塞池中)

Thread类的相关api

  • Thread.currentThread():返回对当前线程对象的引用
  • Thread.interrupted():检测当前线程是否已经中断(调用该方法后后就将该线程的中断标志位设置位false,所以连续两次调用该方法第二次肯定时false)
  • Thread.sleep(long millis):使当前线程睡眠(不会释放锁对象,可以让其他线程有执行的机会)
  • Thread.yield():使当前线程放弃cpu的执行权(有可能立刻又被重新选中继续执行,只可能给优先级更高的线程机会)
  • t.getId():返回该线程的id
  • t.getName():返回该线程的名字
  • t.getPriority():返回该线程的优先级
  • t.getState():返回该线程的状态
  • t.getThreadGroup():返回该线程所属的线程组
  • t.interrupt():将该线程中断(实际并不会中断,只是将中断标志设置为true),如果线程正处在sleep(),join(),wait()方法中时(也就是正在阻塞中)调用该方法,该方法会抛出异常。
  • t.interrupted():检测该线程是否已经中断(对中断标志位不作处理)
  • t.isAlive():检测该线程是否还活着
  • t.isDaemon():检测该线程是否为守护线程
  • t.isInterrupted():检测该线程是否已经中断
  • t.join():在a线程中调用b.join(),则a线程阻塞,直到b线程执行完
  • t.join(long millis):和上面的方法一样,不过a线程阻塞的时间根据long的大小有关,如果达到设定的阻塞时间,就算b线程没有执行完,a线程也会被唤醒。

JDK5之后java.uti.concurrent包下面的一些工具类方便开发

  1. 线程池
    ①为什么需要线程池?
    ------- 主要是为了重复利用线程资源,减少系统在创建和销毁线程上所花的时间和开销;同时也可以限制资源过多,防止出现OOM或执行效率下降
    ②如何获取线程池?
    在jdk5及以上版本中,使用java.util.concurrent.Executors类来创建线程池,该类提供了很多静态方法来创建线程池ExecutorService。
      1、Executors.newFixedThreadPool(int) 创建一个最大规模固定的线程池,如果当前线程不够用且没有超过线程池限制数量,则创建新的线程。如果线程池已满,则会将任务放入等待队列。
      2、Executors.newCachedThreadPool 创建一个最大规模可为Integer.MAX_VALUE 的可缓存的线程池。如果当前线程不够用就增加线程池中的线程数,如果当前线程池中线程过多,则会回收空的线程。
      3、Executors.newSingleThreadExecutor创建一个单线程的线程池,确保任务串行
      4、Executors.newScheduledThreadPool 创建一个固定大小的线程池,以延迟或者固定周期的方式执行,类似于定时器。
    ③执行任务和关闭线程池
      e.execute(Runnable r) :执行任务无返回值
      e.submit(Runnable r) :执行任务返回Future<?> ,实际上是null
      e.submit(Runnable r,T result) : 执行任务返回Future
      e.submit(Callable c) :执行返回Future<?>
      e.invokeAny(Collection<? extends Callable > c):随机执行集合中的一个任务,返回T。如果其中一个任务执行结束(或者抛了一个异常),其他 Callable 将被取消。
      e.invokeAll(Collection<? extends Callable > c):执行集合中所有的任务,返回List<Future>
      e.shutdown():调用该方法后线程池立刻变成shutdown状态,不能再往线程池中增加新的任务否则将会抛出RejectedExecutionException异常,等所有进入队列的任务都执行完毕后关闭线程池
      e.shutdownNow():调用该方法后,线程池立刻变成stop状态,停止接受新的任务,并且试图停止所有正在执行的任务(使用的是Thread.interrupt()方法,不一定能中断正在执行的线程),不会执行等待队列中的任务,然后关闭线程池。
public class Test7 {

    public static void main(String[] args) throws InterruptedException, ExecutionException {
        //获取当前系统cpu的数目
        int availableProcessors = Runtime.getRuntime().availableProcessors();
        ExecutorService fixedThreadPool = Executors.newFixedThreadPool(availableProcessors);
        fixedThreadPool.execute(new MyThread7());
        fixedThreadPool.shutdown();
        
        ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
        Future<?> future = singleThreadExecutor.submit(new MyThread7());
        Future<?> future2 = singleThreadExecutor.submit(new MyThread8());
        System.out.println("future:  "+future.get());
        System.out.println("future2:  "+future2.get());
        singleThreadExecutor.shutdown();
        
        ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
        String result = "这是result";
        Future<String> submit = cachedThreadPool.submit(new MyThread7(),result);
        System.out.println("..."+submit.get());
        cachedThreadPool.shutdown();
        
        ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(availableProcessors);
        //初始延迟3秒钟,只执行一次
        scheduledThreadPool.schedule(new MyThread8(), 3, TimeUnit.SECONDS );
        //初始延迟2秒中,每5秒执行一次
        scheduledThreadPool.scheduleWithFixedDelay(new FixedDelay(), 2, 5, TimeUnit.SECONDS);
        //初始延迟1秒钟,每4秒中执行一次
        scheduledThreadPool.scheduleAtFixedRate(new FixedRate(), 1, 4, TimeUnit.SECONDS);
        
        Thread.sleep(20000);
        scheduledThreadPool.shutdown();
    }
}

class MyThread7 implements Runnable{

    @Override
    public void run() {
        System.out.println("执行代码:"+System.currentTimeMillis()/1000);
    }
    
}

class MyThread8 implements Callable<String>{

    @Override
    public String call() {
        System.out.println("执行代码:"+System.currentTimeMillis()/1000);
        return "执行完成";
    }
    
}

class FixedDelay implements Runnable{

    @Override
    public void run() {
        System.out.println("FixedDelay执行代码:"+System.currentTimeMillis()/1000);
    }
    
}
class FixedRate implements Runnable{

    @Override
    public void run() {
        System.out.println("FixedRate执行代码:"+System.currentTimeMillis()/1000);
    }
    
}

执行结果:
执行代码:1523348201
执行代码:1523348201
future:  null
执行代码:1523348201
future2:  执行完成
执行代码:1523348201
...这是result
FixedRate执行代码:1523348202
FixedDelay执行代码:1523348203
执行代码:1523348204
FixedRate执行代码:1523348206
FixedDelay执行代码:1523348208
FixedRate执行代码:1523348210
FixedDelay执行代码:1523348213
FixedRate执行代码:1523348214
FixedRate执行代码:1523348218
FixedDelay执行代码:1523348218

④ThreadPoolExecutor学习
其实通过源码可知newFixedThreadPool、newCachedThreadPool、newSingleThreadExecutor 三种线程池的创建都是通过调用如下的方法来创建的。

public ThreadPoolExecutor(int corePoolSize,//核心线程池大小
                              int maximumPoolSize,//最大线程池大小
                              long keepAliveTime,//线程执行完成后在线程池中的缓存时间,也就是线程空闲多长时间后会被回收
                              TimeUnit unit,//时间单位TimeUnit.SECONDS
                              BlockingQueue<Runnable> workQueue,//线程缓冲队列,当线程池线程运行超过一定线程时并满足一定的条件,待运行的线程会放入到这个队列  
                              ThreadFactory threadFactory,//线程工厂,用来创建线程  
                              RejectedExecutionHandler handler//当缓冲队列也放不下线程时的拒绝策略  
  ){
        if (corePoolSize < 0 ||
            maximumPoolSize <= 0 ||
            maximumPoolSize < corePoolSize ||
            keepAliveTime < 0)
            throw new IllegalArgumentException();
        if (workQueue == null || threadFactory == null || handler == null)
            throw new NullPointerException();
        this.acc = System.getSecurityManager() == null ?
                null :
                AccessController.getContext();
        this.corePoolSize = corePoolSize;
        this.maximumPoolSize = maximumPoolSize;
        this.workQueue = workQueue;
        this.keepAliveTime = unit.toNanos(keepAliveTime);
        this.threadFactory = threadFactory;
        this.handler = handler;
    }

线程池总结:
  ThreadPoolExecutor对象初始化时,不创建任何执行线程,当有新任务进来时,才会创建线程来执行任务。当目前执行线程的总数小于核心线程大小时,所有新加入的任务,都会创建新线程来处理。当目前执行线程的总数大于或等于核心线程时,所有新加入的任务,都放入任务缓存队列中。当目前执行线程的总数大于或等于核心线程,并且缓存队列已满,同时此时线程总数小于线程池的最大规模,那么创建新线程,协助处理新的任务。当所有线程都在执行,线程池大小已经达到上限,并且缓存队列已满时,就rejectHandler拒绝新的任务。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值