zoukankan      html  css  js  c++  java
  • 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提供了一个更加面对对象的锁,在该锁中提供了更多的操作锁的功能!

  • 相关阅读:
    mysql 中文字段排序( UTF8按拼音首字母排序)
    输入输出挂
    HDU 6301 贪心
    HDU1533 最小费用最大流
    POJ 2135 最小费用最大流 入门题
    HDU 6278 主席树(区间第k大)+二分
    HDU3549 最大流 裸题
    2018牛客网暑期ACM多校训练营(第一场)D图同构,J
    POJ 1804 逆序对数量 / 归并排序
    Codeforces Round #489 (Div. 2) B、C
  • 原文地址:https://www.cnblogs.com/postgredingdangniu/p/9543102.html
Copyright © 2011-2022 走看看