2018-08-27Runnable+Callable创建线程池+死锁概念+Lock同步锁

线程的创建和销毁很耗费计算机的资源,由此衍生出了线程池的概念!

线程池,其实就是一个容纳多个线程的容器,其中的线程可以反复使用,省去了频繁创建线程对象的操作,无需反复创建线程而消耗过多资源!

//线程放在线程池中,用的时候拿出来使用,不用的时候放回池子中!

强调:多线程很重要,线程池主要用来解决线程生命周期开销问题和资源不足问题!

实现线程池的两种方式:

实现Runnable接口:缺点无返回值,不可以throws抛出异常!

实现Callable接口:有返回值,可以throws抛出异常!

示例代码(重要):

package com.oracle.duoxiancheng20180827;
//实现Runnable接口,重写run方法:
public class MyRunnable implements Runnable {
    //无返回值,不可以抛异常:
    public void run(){
        for(int i=0;i<50;++i){
            System.out.println("Run……"+i);
        }
    }
}

package com.oracle.duoxiancheng20180827;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Demo01 {
    public static void main(String[] args) {
        //获取线程池对象(从线程池工厂中获得):
        ExecutorService es=Executors.newFixedThreadPool(2);
        //创建Runnable接口子类对象:
        MyRunnable mr=new MyRunnable();
        //提交Runnable子类对象(线程池自动选一条线程执行提交上来的任务):
        es.submit(mr);
        //在Main方法中写一个for循环,试验有没有多线程:
        for(int i=0;i<50;++i){
            System.out.println("Main……"+i);
        }
        //以上代码走完run方法该线程就灭了,但是该线程在线程池中,除非shutdown该线程池,不然该线程是不死的!
        //没有线程池之后,程序执行网run()方法,该线程就被Terminated,有了线程池之后,线程执行完会归还到线程池中,调用线程池的shutdown()方法关闭线程池,该线程才会关闭!
        //关闭线程池:
        es.shutdown();
        //关闭线程池之后,看到执行过后terminate已经灭了!
        //线程池内线程数量尽量开的大一点,不然多余线程会等前面线程结束之后再加入运行!
    }
}

package com.oracle.duoxiancheng20180827;
import java.util.concurrent.Callable;
//Callable泛型就是Call方法的返回值类型!
public class MyCallable implements Callable<String> {
    public String call() throws Exception {
        return "这是Call方法!";
    }
}

package com.oracle.duoxiancheng20180827;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class Demo02 {
    public static void main(String[] args) throws InterruptedException, ExecutionException {
        //Callable专用于线程池,有返回值,可以throws抛出异常!
        //获取线程池:
        ExecutorService es=Executors.newFixedThreadPool(2);
        //创建Callable子类:
        MyCallable mc=new MyCallable();
        //提交Callable子类:
        Future<String> fu=es.submit(mc);
        //默认调用toString方法,打印出地址!
        System.out.println(fu);
        //调用Future对象fu的.get()方法,打印出mc的返回值:
        System.out.println(fu.get());
        //关闭线程池:
        es.shutdown();
    }
}

package com.oracle.duoxiancheng20180827;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class Demo03 {
    public static void main(String[] args) throws InterruptedException, ExecutionException {
        //异步计算0-100,0-200的和:
        //通过线程工厂获取线程池:
        ExecutorService es=Executors.newFixedThreadPool(2);
        //创建Callable对象,并传参:
        YBJSCallable yc1=new YBJSCallable(100);
        YBJSCallable yc2=new YBJSCallable(200);
        //扔进线程池:
        Future<Integer> fu1=es.submit(yc1);
        Future<Integer> fu2=es.submit(yc2);
        //打印返回结果:
        System.out.println(fu1.get());
        System.out.println(fu2.get());
    }
}

package com.oracle.duoxiancheng20180827;
import java.util.concurrent.Callable;
//异步计算Callable类:
public class YBJSCallable implements Callable<Integer> {
    private Integer getNum;
    //通过构造方法传参:
    YBJSCallable(Integer getNum){
        this.getNum=getNum;
    }
    //Call方法无法传参:
    public Integer call() throws Exception {
        int sum=0;
        for(int i=0;i<=getNum;++i){
            sum+=i;
        }
        return sum;
    }
    //由于Callable的call()方法无法传参,所以声明一个修饰符为private的成员变量,再写一个构造方法,用于传参!
}

package com.oracle.duoxiancheng20180827;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class Demo03 {
    public static void main(String[] args) throws InterruptedException, ExecutionException {
        //异步计算0-100,0-200的和:
        //通过线程工厂获取线程池:
        ExecutorService es=Executors.newFixedThreadPool(2);
        //创建Callable对象,并传参:
        YBJSCallable yc1=new YBJSCallable(100);
        YBJSCallable yc2=new YBJSCallable(200);
        //扔进线程池:
        Future<Integer> fu1=es.submit(yc1);
        Future<Integer> fu2=es.submit(yc2);
        //打印返回结果:
        System.out.println(fu1.get());
        System.out.println(fu2.get());
    }
}

package com.oracle.homework;
import java.util.concurrent.Callable;
//计算两个数相加:
public class PlusCallable implements Callable {
    //定义接收两个数的私有成员变量:
    private Integer firNum;
    private Integer secNum;
    //定义构造方法用于传参:
    public PlusCallable(Integer firNum, Integer secNum) {
        super();
        this.firNum = firNum;
        this.secNum = secNum;
    }
    //GET+SET方法:
    public Integer getFirNum() {
        return firNum;
    }
    public void setFirNum(Integer firNum) {
        this.firNum = firNum;
    }
    public Integer getSecNum() {
        return secNum;
    }
    public void setSecNum(Integer secNum) {
        this.secNum = secNum;
    }
    //重写call()方法:
    public Object call() throws Exception {
        return firNum+secNum;
    }
}

package com.oracle.homework;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class TestPlusCall {
    public static void main(String[] args) throws InterruptedException, ExecutionException {
        //从线程池工厂获取线程池对象:
        ExecutorService es=Executors.newFixedThreadPool(1);
        //创建线程任务并传参:
        PlusCallable pc1=new PlusCallable(23,56);
        PlusCallable pc2=new PlusCallable(66,99);
        //Future对象获取返回值:
        //执行完第一个线程,扔回线程池里,接着执行第二个,通过一个线程运算的两个结果!
        Future<Integer> fu1=es.submit(pc1);
        Future<Integer> fu2=es.submit(pc2);
        //打印结果:
        System.out.println(fu1.get());
        System.out.println(fu2.get());
        //关闭线程池:
        es.shutdown();
    }
}

死锁演示:

package com.oracle.tickets;
public class LockA {
    private LockA(){
        
    }
    public final static LockA LockA=new LockA();
}

package com.oracle.tickets;
public class LockB {
    private LockB(){
        
    }
    public final static LockB LockB=new LockB();
}

package com.oracle.tickets;
public class DeadLock implements Runnable {
    private int i=0;
    public void run() {
        while(true){
            if(i%2==0){
                synchronized(LockA.LockA){
                    System.out.println("if……LockA");
                    synchronized(LockB.LockB){
                        System.out.println("if……LockB");
                    }
                }
            }else{
                synchronized(LockB.LockB){
                    System.out.println("else……LockB");
                    synchronized(LockA.LockA){
                        System.out.println("else……LockA");
                    }
                }
            }
            ++i;
        }
    }
}

package com.oracle.tickets;
public class Demo03 {
    public static void main(String[] args) {
        DeadLock DeadLock=new DeadLock();
        Thread th1=new Thread(DeadLock);
        Thread th2=new Thread(DeadLock);
        th1.start();
        th2.start();
    }
}

package com.oracle.tickets;
public class SafeTicket implements Runnable {
    private static int ticNum=100;
    private Object obj=new Object();
    public void run(){
        while(true){
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            synchronized(obj){
                if(ticNum>0){
                    System.out.println(Thread.currentThread().getName()+"出售第"+ticNum--+"张票!");
                }
            }
        }
    }
    public void run(){
        while(true){
            sale();
        }
    }
    //是new SafeTicket()对象,this关键字!
    public static synchronized void sale(){
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        if(ticNum>0){
            System.out.println(Thread.currentThread().getName()+"出售第"+ticNum--+"张票!");
        }
    }
}

package com.oracle.tickets;
public class Demo03 {
    public static void main(String[] args) {
        DeadLock DeadLock=new DeadLock();
        Thread th1=new Thread(DeadLock);
        Thread th2=new Thread(DeadLock);
        th1.start();
        th2.start();
    }
}

package com.oracle.tickets;
public class Demo01 {
    public static void main(String[] args) {
        SafeTicket th=new SafeTicket();
        Thread t1=new Thread(th);
        Thread t2=new Thread(th);
        Thread t3=new Thread(th);
        t1.start();
        t2.start();
        t3.start();
    }
}

package com.oracle.tickets;
public class Demo02 {
    public static void main(String[] args) {
        NewTickets th=new NewTickets();
        Thread t1=new Thread(th);
        Thread t2=new Thread(th);
        Thread t3=new Thread(th);
        t1.start();
        t2.start();
        t3.start();
    }
}

线程同步锁:

①    Synchronized

②    Lock接口

同步代码块: 在代码块声明加上synchronized!

synchronized (锁对象) {

       可能会产生线程安全问题的代码!

}

同步代码块中的锁对象可以是任意的对象,但多个线程时,要使用同一个锁对象才能够保证线程安全!

对象锁,同步锁,对象监视器-->都是同步锁!

同步怎么保证安全性?同步中有锁,没有锁的线程不能执行,只能等!

同步方法:在方法声明上加上synchronized!

public synchronized void method(){

     可能会产生线程安全问题的代码!

}

同步方法中的锁对象是this,即new Tickets()对象!

静态同步方法: 在方法声明上加上static synchronized!

public static synchronized void method(){

可能会产生线程安全问题的代码!

}

静态同步方法中的锁对象是本类字节码对象类名.class!

StringBuilder和StringBuffer区别:

StringBuilder速度快安全性差

StringBuffer速度慢安全性高-->带同步锁,多线程时要等锁回来!

//多线程共享同一个数据会出现线程安全问题!

线程中出现多个同步锁时,如果同步锁中出现了其他的同步锁;容易引发程序的无限等待,这种现象我们称为死锁!

Lock接口:

Lock提供了一个更加面对对象的锁,在该锁中提供了更多的操作锁的功能!

原文地址:https://www.cnblogs.com/postgredingdangniu/p/9543102.html