过程和线程

~ 线程是在一个过程中,并发执行的多个程序逻辑,线程是过程执行的单位。
~ 一个过程中至多有一个线程, 而这个线程被称为主线程, 主线程是一个程序的入口, main 就是由主线程来执行的。
 

线程创立三种形式:

1.继承Thread类
2.实现Rnnable接口
3.实现Callable接口  

继承Thread

public class thread extends Thread{     @Override    public void run() {        for (int i = 0; i < 20; i++) {            System.out.println("这是run线程"+i);        }    }        public static void main(String[] args) {         // 开启run线程 start 是同时运行 run办法是先执行run办法 在执行主线程        thread thread = new thread();        thread.start();// 开启线程        for (int i = 0; i < 200; i++) {            System.out.println("这是main线程"+i);        }    }}

 

实现Rnnable接口

public class runnable implements Runnable{    @Override    public void run() {        for (int i = 0; i < 20; i++) {            System.out.println("这是run线程"+i);        }    }        public static void main(String[] args) {        runnable runnable = new runnable();// 创立线程对象        new Thread(runnable,"定义线程名").start();// 须要一个Thread对象        for (int i = 0; i < 200; i++) {            System.out.println("这是main线程"+i);        }    }}

 

实现Callable接口

public class callable implements Callable<Object> {      @Override    public Object call() throws Exception {        Object object = new Object();        return object;    }     public static void main(String[] args) throws ExecutionException, InterruptedException {        // 创立线程        callable callable = new callable();        // 创立执行服务        ExecutorService pool = Executors.newFixedThreadPool(3);        // 执行线程 获取后果        Future<Object> res = pool.submit(callable);        Object obj = res.get();        // 敞开服务        pool.shutdownNow();    }}

~ run办法和start办法两者是有区别的,run会先运行run里代码在运行主线程,start是同时运行。

~ 线程开启并不一定立刻执行,是由cpu调度的,人为无奈干涉。

~ 获取以后线程的名字

Thread.currentThread().getName();

 ~ 获取线程的状态

State state = thread.getState();

线程的五种状态

  • 初始状态 new当创立了一个线程时,会进入此状态。
  • 就绪状态 当初始状态调用了start()办法时,会进入此状态。
  • 运行状态 当就绪状态的线程取得cpu工夫片,即调度到它,进入运行状态。
  • 梗塞状态 当调用sleep,wait办法或同步锁定,线程进入梗塞,代码不往下执行,梗塞事件完结后从新进入* 就绪状态,期待cpu调度。

终止状态 线程中断或者执行完所有代码,进入终止状态。

synchronized 隐式锁

synchronize有两种时用,同步办法,同步代码块。synchronize同步办法默认锁的时this,即以后对象,同步代码块能够锁任何对象。死锁线程单方锁了对方所须要的临界资源,导致单方都处于梗塞状态。

同步代码块:

        synchronized (obj){//obj 须要锁的对象                    }

lock 显示锁

不同于synchronize(修饰符),lock是可重入锁,是一个对象,他只能锁代码块,由jdk1.5推出的新个性,lock已本身为标记,代替了临界资源互斥锁标记。

创立lock锁:

 private final ReentrantLock lock = new ReentrantLock(); // 创立lock锁对象 try{    lock.lock(); // 加锁    ... }finally{    lock.unlock(); // 解锁 }

线程之间的通信

~ 线程间的通信 须要临界资源来调用相应的办法 因为锁标记是临界资源所领有的
 
wait():当临界资源调用wait()办法时 以后线程 放弃工夫片 放弃互斥锁标记 进入期待区(进入阻塞状态) 

notify():当临界资源调用notify()时会依据肯定策略 唤醒期待区中的某个线程 该线程从新回归就绪状态

notifyAll():当临界资源调用notifyAll()时 唤醒期待区中的所有线程 所有线程进入就绪状态

 

sleep()和wait()区别

它俩来自不同的类,sleep()是Thread类的,wait()是来自于Object类。
sleep() 只让出了CPU,却不会开释对象锁,处于梗塞状态,它须要设置休眠工夫。wait()会放弃对象锁,并让出cpu资源,处于期待状态,应用notify()和notifyAll()来唤醒。
sleep() 会抛出InterruptedException异样,须要进行相干解决,而wait()不须要捕捉异样。
 

线程平安的汇合

CopyOnWriteArrayList :所在包 java . util . concurrent ;读操作远远大于写操作时,效率高,在写时会先创立正本将写操作进行结束时,再替换原容器,保障读的正确性,但写的效率很低。
 
ConcurrentHashMap : 所在包 java . util . concurrent ; 进步了 HashMap 的并发效率,应用了分级锁,将本来的 hash 表分,成了16 段,一个 hash 表时,有一个线程操作任意一个地位,都会导致 hash 被锁,但分成了 16 段加锁时,一个线程拜访一部分时,其余线程能够拜访其余局部。
 
 
 

线程池

~ 顾名思义,一个池子用来装线程的容器,可已设定线程调配数量下限,将事后创立线程对象存入池中,并重用线程池中的线程。

~ 益处是缩小创立和销毁线程的次数。

线程池的根本接口:Executor

线程池接口:ExecutorService

线程池工具类:Executors,用于创立线程。

newSingleThreadPool 创立一个单线程的线程池。这个线程池只有一个线程在工作,也就是相当于单线程串行执行所有工作。如果这个惟一的线程因为异样完结,那么会有一个新的线程来代替它, 此线程池保障所有工作的执行程序依照工作的提交程序执行。

   public class ThreadPoolExecutorTest {       public static void main(String[] args) {           ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();           for (int i = 0; i < 10; i++) {               final int index = i;               singleThreadExecutor.execute(new Runnable() {                   public void run() {                       try {                           System.out.println(index);                           Thread.sleep(2000);                       } catch (InterruptedException e) {                           e.printStackTrace();                       }                   }               });           }       }   }

 

newFixedThreadPool 创立固定大小的线程池。每次提交一个工作就创立一个线程,直到线程达到线程池的最大大小。某个线程因为执行异样而完结,那么线程池会补充一个新线程。

   public class ThreadPoolExecutorTest {       public static void main(String[] args) {           ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);           for (int i = 0; i < 10; i++) {               final int index = i;               fixedThreadPool.execute(new Runnable() {                   public void run() {                       try {                           System.out.println(index);                           Thread.sleep(2000);                       } catch (InterruptedException e) {                           e.printStackTrace();                       }                   }               });           }       }   }

newCachedThreadPool 创立一个可缓存的线程池。如果线程池的大小超过了解决工作所须要的线程,那么就会回收局部变量(60秒不执行工作)的线程,当工作数减少时,此线程池又能够智能的增加新线程来解决工作。此线程池不会对线程池大小做限度,线程池大小齐全依赖于操作系统(或者说JVM)可能创立的最大线程大小。

    public class ThreadPoolExecutorTest {        public static void main(String[] args) {            ExecutorService cachedThreadPool = Executors.newCachedThreadPool();            for (int i = 0; i < 10; i++) {                final int index = i;                try {                    Thread.sleep(index * 1000);                } catch (InterruptedException e) {                    e.printStackTrace();                }                cachedThreadPool.execute(new Runnable() {                    public void run() {                        System.out.println(index);                    }                });            }        }    }

newScheduledThreadPool 创立一个定长的线程池,而且反对定时的以及周期性的工作执行,反对定时及周期性工作执行。

    public class ThreadPoolExecutorTest {        public static void main(String[] args) {            ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);            scheduledThreadPool.schedule(new Runnable() {                public void run() {                    System.out.println("delay 3 seconds");                }            }, 3, TimeUnit.SECONDS);        }    }

 

应用

public static void main(String[] args) {        //创立线程工作对象        MyRunnable02 mr=new MyRunnable02();        //获取线程池对象        ExecutorService es=Executors.newFixedThreadPool(2);        //调用办法执行线程工作        es.submit(mr);        es.submit(mr);        //销毁线程池        es.shutdown();}

最初

欢送关注公众号:前程有光,支付一线大厂Java面试题总结+各知识点学习思维导+一份300页pdf文档的Java外围知识点总结! 这些材料的内容都是面试时面试官必问的知识点,篇章包含了很多知识点,其中包含了有基础知识、Java汇合、JVM、多线程并发、spring原理、微服务、Netty 与RPC 、Kafka、日记、设计模式、Java算法、数据库、Zookeeper、分布式缓存、数据结构等等。