java多线程相关

1.创建线程的三种方式

  1.声明线程类继承Thread类,重写run()方法,然后使用的时候,new对象调用start()方法开始线程执行。

代码实例

public class MyThread extends Thread{//继承Thread类   

  public void run(){

  //重写run方法   

} }

public class Main {   

  public static void main(String[] args){     

  new MyThread().start();//创建并启动线程  

 } }

  2.声明线程类实现Runnable接口,重写run()方法,使用时new 对象,将其传入到new的Thread对象中,Runnable接口实际上是线程要执行的任务,所以我们还要创建一个线程对象来执行这个任务.

代码实例: public class MyThread2 implements Runnable {//实现Runnable接口   

public void run(){

  //重写run方法   

} }

public class Main {

  public static void main(String[] args){

    //创建并启动线程     

    MyThread2 myThread=new MyThread2();    

      Thread thread=new Thread(myThread);     

    thread().start();     

}

}

  3.Callable接口,和Runnable类似,里边只有一个call方法,不同的是,这个方法可以报出异常,并且有返回值。但是呢,这个call方法不是人为调用的,而是执行了Thread对象的start方法自动调用了,所以要想个办法获得call方法的返回值,所以就有了Future类,它创建的时候需要一个Callable,它的get方法就可以获得这个返回值,还有个问题就是Thread只能接收Runnable接口作为参数,所以要有个接口既实现了了Future接口能获得返回值,还实现了Runnable能传给Thread,这个接口就是RunnableFuture,它的实现类是FutureTask。

      new Thread(new FutureTask(new Callable()<Integer>{})<Integer>)要给出call方法返回值类型

优缺点:

  Runnable方式更好,可以将任务交给不同的线程执行,实现资源共享,并且可以继承其他类。

  如果需要异常处理或者执行后需要返回值那Callable更好。

 

2.阻塞队列:1.多线程安全。2.消费者来取队列内容时,如果队列为空,则阻塞等待。生产者来放内容时,如果队列满了,则阻塞等待。

 

3.线程池

ThreadPoolExecutor(int corePoolSize,

              int maximumPoolSize,

           long keepAliveTime,

           TimeUnit unit,

           BlockingQueue<Runnable> workQueue,

           ThreadFactory threadFactory) { this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, defaultHandler); }

corePoolSize:核心线程数,线程池自带的线程数量。

maximumPoolSize:最大线程数,当队列满了,并且当前线程数量小于最大线程数,则创建新的线程从队列中取任务执行。

keepAliveTime:当队列中没有任务时,对于核心数目的线程会保持这段时间后销毁。

unit:枚举类型,代表keepAliveTime的单位是什么。

workQueue:装任务的队列,不同队列直接决定了线程池的任务策略。

ThreadFactory:默认的,创建线程的工厂

defaultHandler:任务提交失败时执行,可以抛出异常之类的。

4.线程池的种类

  

  FixedThreadPool :固定大小的线程池,底层还是ThreadPoolExcuter,只是设置了一些参数。核心线程数量和最大线程数量相等,传入进来,是无界队列。

  CachedThreadPool:可缓存的线程池,底层还是ThreadPoolExcuter,只是设置了一些参数。核心线程数为零,最大线程数为最大值,等待时间是60s,队列是SynchronousQueue,没有存储空间,

来个任务,就创建一个线程处理。

  SingleThreadExecutor  :单例线程池,底层还是ThreadPoolExcuter,只是设置了一些参数,核心线程和最大线程都为1,队列是普通的LinkedBlockingQueue。

  ScheduledThreadPool  :可调度的线程池,实现定时或者延时执行。

// 1. 创建 定时线程池对象 & 设置线程池线程数量固定为5
ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);

// 2. 创建好Runnable类线程对象 & 需执行的任务
Runnable task =new Runnable(){
       public void run(){
              System.out.println("执行任务啦");
          }
    };
// 3. 向线程池提交任务:schedule()
scheduledThreadPool.schedule(task, 1, TimeUnit.SECONDS); // 延迟1s后执行任务
scheduledThreadPool.scheduleAtFixedRate(task,10,1000,TimeUnit.MILLISECONDS);// 延迟10ms后、每隔1000ms执行任务

// 4. 关闭线程池
scheduledThreadPool.shutdown();

5.CAS:在java.util.current.atomic包下面,采用了CAS机制来实现加锁,对变量使用。

  CAS+volatile实现了锁的作用

  sychronized:原子性、可见性、顺序性

  volatile:可见性、顺序性

  CAS:原子性

posted @ 2019-11-04 13:27  高鸣泽  阅读(151)  评论(0)    收藏  举报