zoukankan      html  css  js  c++  java
  • java多线程

    1.不加任何同步措施

    package jianzhioffer;

    //出现不安全问题
    /**
    * 吐钱成功,吐出钞票:800.0
    吐钱成功,吐出钞票:800.0
    余额为:200.0
    余额为:-600.0
    */

    class Account{
        public  String accountNo;
        public double balance;
        public Account(String accountNo,double balance){
            this.accountNo=accountNo;
            this.balance=balance;
        }
        public int hashcode(){
            return accountNo.hashCode();
        }
        public boolean equals(Object obj){
            if(obj!=null&&obj.getClass()==Account.class){
                Account target=(Account)obj;
                return target.accountNo.equals(accountNo);
            }
            return false;
        }
    }
    class DrawThread extends Thread{
        public Account account;
        public double drawAmount;
        public DrawThread(String name,Account account,double drawAmount){
            super(name);
            this.account=account;
            this.drawAmount=drawAmount;
        }
        public void run(){
            if(account.balance>=drawAmount){
                System.out.println("吐钱成功,吐出钞票:"+drawAmount);
                try{
                    Thread.sleep(1);
                }catch(InterruptedException ex){
                    ex.printStackTrace();
                }
                account.balance=account.balance-drawAmount;
                System.out.println("余额为:"+account.balance);
            }else{
                System.out.println(getName()+"取钱失败,余额不足");
            }
    
        }
    }
    public class testSynchronize1 extends Thread{
        public static void main(String[] args) throws InterruptedException {
            Account acc=new Account("1234567", 1000);
            new DrawThread("甲",acc,800).start();
            // Thread.sleep(100);
            new DrawThread("已",acc,800).start();
            
    
    
        }
        
    }

    2. 使用同步代码块

    package jianzhioffer;
    
    
    class Account{
        public  String accountNo;
        public double balance;
        public Account(String accountNo,double balance){
            this.accountNo=accountNo;
            this.balance=balance;
        }
        public int hashcode(){
            return accountNo.hashCode();
        }
        public boolean equals(Object obj){
            if(obj!=null&&obj.getClass()==Account.class){
                Account target=(Account)obj;
                return target.accountNo.equals(accountNo);
            }
            return false;
        }
    }
    class DrawThread extends Thread{
        public Account account;
        public double drawAmount;
        public DrawThread(String name,Account account,double drawAmount){
            super(name);
            this.account=account;
            this.drawAmount=drawAmount;
        }
        public void run(){
            //1.同步代码块,account是同步监视器,在执行这个代码块之前锁定account
            synchronized(account){
            if(account.balance>=drawAmount){
                System.out.println("吐钱成功,吐出钞票:"+drawAmount);
                try{
                    Thread.sleep(1);
                }catch(InterruptedException ex){
                    ex.printStackTrace();
                }
                account.balance=account.balance-drawAmount;
                System.out.println("余额为:"+account.balance);
            }else{
                System.out.println(getName()+"取钱失败,余额不足");
            }
        }
            //同步代码块结束,释放同步锁(同步监视器account)
        }
    }
    public class testSynchronize1 extends Thread{
        public static void main(String[] args) throws InterruptedException {
            Account acc=new Account("1234567", 1000);
            new DrawThread("甲",acc,800).start();
            // Thread.sleep(100);
            new DrawThread("已",acc,800).start();
            
    
    
        }
        
    }

    3.使用同步方法

    package jianzhioffer;
    
    
    class Account{
        public  String accountNo;
        public double balance;
        public Account(String accountNo,double balance){
            this.accountNo=accountNo;
            this.balance=balance;
        }
        public int hashcode(){
            return accountNo.hashCode();
        }
        public boolean equals(Object obj){
            if(obj!=null&&obj.getClass()==Account.class){
                Account target=(Account)obj;
                return target.accountNo.equals(accountNo);
            }
            return false;
        }
        //监视器是this,对于同一个账户,一次只有一个线程可以获得的对account的锁定,然后进入draw方法进行取钱
        public synchronized void draw(double drawAmount){
            if(balance>=drawAmount){
                System.out.println("吐钱成功,吐出钞票:"+drawAmount);
                try{
                    Thread.sleep(1);
                }catch(InterruptedException ex){
                    ex.printStackTrace();
                }
                balance-=drawAmount;
                System.out.println("余额为:"+balance);
    
            }else{
                System.out.println(Thread.currentThread().getName()+"取钱失败,余额不足");
            }
        }
    }
    class DrawThread extends Thread{
        public Account account;
        public double drawAmount;
        public DrawThread(String name,Account account,double drawAmount){
            super(name);
            this.account=account;
            this.drawAmount=drawAmount;
        }
        public void run(){
            
            account.draw(drawAmount);
            
        }
    }
    public class testSynchronize1 extends Thread{
        public static void main(String[] args) throws InterruptedException {
            Account acc=new Account("1234567", 1000);
            new DrawThread("甲",acc,800).start();
            // Thread.sleep(100);
            new DrawThread("已",acc,800).start();
    
        }
        
    }

    同步监视器的释放:

    a.执行结束

    b.break,return

    c.error

    d.执行了同步监视器的wait()

    不会释放的情况

    a.sleep(),yeild()

    b. suspend挂起

    4. 同步锁

    package jianzhioffer;
    
    import java.util.concurrent.locks.ReentrantLock;
    
    class Account {
        public String accountNo;
        public double balance;
        //可重入锁
        public final ReentrantLock lock = new ReentrantLock();
    
        public Account(String accountNo, double balance) {
            this.accountNo = accountNo;
            this.balance = balance;
        }
    
        public int hashcode() {
            return accountNo.hashCode();
        }
    
        public boolean equals(Object obj) {
            if (obj != null && obj.getClass() == Account.class) {
                Account target = (Account) obj;
                return target.accountNo.equals(accountNo);
            }
            return false;
        }
    
        public void draw(double drawAmount) throws InterruptedException {
            //加上锁
            lock.lock();
            try {
                if (balance >= drawAmount) {
                    System.out.println("吐钱成功,吐出钞票:" + drawAmount);
                    try {
                        Thread.sleep(1);
                    } catch (InterruptedException ex) {
                        ex.printStackTrace();
                    }
                    balance -= drawAmount;
                    System.out.println("余额为:" + balance);
    
                } else {
                    System.out.println(Thread.currentThread().getName() + "取钱失败,余额不足");
                }
            } finally {
                //在finally中去掉锁确保可释放
                lock.unlock();
            }
        }
    }
    
    class DrawThread extends Thread {
        public Account account;
        public double drawAmount;
    
        public DrawThread(String name, Account account, double drawAmount) {
            super(name);
            this.account = account;
            this.drawAmount = drawAmount;
        }
    
        public void run() {
            try {
                account.draw(drawAmount);
            } catch (InterruptedException e) {
                
                e.printStackTrace();
            }
        }
    }
    public class testSynchronize1 extends Thread{
        public static void main(String[] args) throws InterruptedException {
            Account acc=new Account("1234567", 1000);
            new DrawThread("甲",acc,800).start();
            // Thread.sleep(100);
            new DrawThread("已",acc,800).start();
    
        }
        
    }

    5.死锁

    package jianzhioffer;
    class A{
        public synchronized void foo(B b){
            System.out.println("当前线程名:"+Thread.currentThread().getName()+"进入了A实例的foo方法");
            try{
                Thread.sleep(200);
            }catch(InterruptedException e){
                e.printStackTrace();
            }
            System.out.println("当前线程名:"+Thread.currentThread().getName()+"企图调用B的last方法");
            b.last();
        }
        public synchronized void last(){
            System.out.println("进入了A的last内部");
        }
    }
    class B{
        public synchronized void foo(A a){
            System.out.println("当前线程名:"+Thread.currentThread().getName()+"进入了B实例的foo方法");
            try{
                Thread.sleep(200);
            }catch(InterruptedException e){
                e.printStackTrace();
            }
            System.out.println("当前线程名:"+Thread.currentThread().getName()+"企图调用A的last方法");
            a.last();
        }
        public synchronized void last(){
            System.out.println("进入了B的last内部");
        }
    }
    public class DeadLock implements Runnable{
        A a=new A();
        B b=new B();
        public void init(){
            Thread.currentThread().setName("主线程");
            a.foo(b);
            System.out.println("进入主线程之后");
        }
        @Override
        public void run() {
            Thread.currentThread().setName("副线程");
            b.foo(a);
            System.out.println("进入副线程之后");
    
        }
        public static void main(String[] args) {
            DeadLock dl=new DeadLock();
            //以dl为target启动新线程
            new Thread(dl).start();
            //通过init()方法作为新线程
            dl.init();
        }
    
        
    }

    一定要两个方法都是同步方法

    package jianzhioffer;
    import java.util.Date;
    public class DeadLock2 {
        public static String obj1="obj1";
        public static String obj2="obj2";
        public static void main(String[] args) {
            LockA la=new LockA();
            new Thread(la).start();
            LockB lb=new LockB();
            new Thread(lb).start();
    
        }
    
        
    }
    class LockA implements Runnable{
    
        @Override
        public void run() {
            // TODO Auto-generated method stub
            try{
                System.out.println(new Date().toString()+"LockA开始执行");
                while(true){
                    synchronized(DeadLock2.obj1){
                        System.out.println(new Date().toString()+"LockA锁住了obj1");
                        Thread.sleep(300);//给B锁住机会
                        synchronized(DeadLock2.obj2){
                            System.out.println(new Date().toString()+"LockA锁住了obj2");
                            Thread.sleep(60000);//占用了就不放,为了测试
                        }
    
                    }
    
                }
            }catch(Exception e){
                e.printStackTrace();
    
            }
    
        }
    
    }
    class LockB implements Runnable{
    
        @Override
        public void run() {
            // TODO Auto-generated method stub
            try{
                System.out.println(new Date().toString()+"LockB开始执行");
                synchronized(DeadLock2.obj2){
                    System.out.println(new Date().toString()+"LockB锁住了obj2");
                    Thread.sleep(300);
                    synchronized(DeadLock2.obj1){
                        System.out.println(new Date().toString()+"LockB锁住了obj1");
                        Thread.sleep(60000);//占用了就不放,为了测试
                    }
    
                }
            }catch(Exception e){
                e.printStackTrace();
            }
    
        }
    
    }

    解决方法

    package jianzhioffer;
    
    import java.util.Date;
    import java.util.concurrent.Semaphore;
    import java.util.concurrent.TimeUnit;
    
    public class unlock {
        public static String obj1 = "obj1";
        public static final Semaphore a1 = new Semaphore(1);
        public static String obj2 = "obj2";
        public static final Semaphore a2 = new Semaphore(1);
    
        public static void main(String[] args) {
          LockAa la = new LockAa();
          new Thread(la).start();
          LockBa lb = new LockBa();
          new Thread(lb).start();
        }
    
    }
    
    class LockAa implements Runnable {
        @Override
        public void run() {
            try {
            System.out.println(new Date().toString() + " LockA 开始执行");
            while (true) {
                if (unlock.a1.tryAcquire(1, TimeUnit.SECONDS)) {
                    System.out.println(new Date().toString() + " LockA 锁住 obj1"); 
                    if (unlock.a2.tryAcquire(1, TimeUnit.SECONDS)) {
                        System.out.println(new Date().toString() + " LockA 锁住 obj2");
                        Thread.sleep(60 * 1000); // do something
                     }else{
                        System.out.println(new Date().toString() + "LockA 锁 obj2 失败");
                     }          
                 }else{
                    System.out.println(new Date().toString() + "LockA 锁 obj1 失败");
                 }
                unlock.a1.release(); // 释放
                unlock.a2.release();
                Thread.sleep(1000); // 马上进行尝试,现实情况下do something是不确定的 
            }
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        }
        
    }
    class LockBa implements Runnable {
        @Override
        public void run() {
            try {
            System.out.println(new Date().toString() + " LockB 开始执行");
            while (true) {
                if (unlock.a2.tryAcquire(1, TimeUnit.SECONDS)) {
                    System.out.println(new Date().toString() + " LockB 锁住 obj2"); 
                    if (unlock.a1.tryAcquire(1, TimeUnit.SECONDS)) {
                        System.out.println(new Date().toString() + " LockB 锁住 obj1");
                        Thread.sleep(60 * 1000); // do something
                     }else{
                        System.out.println(new Date().toString() + "LockB 锁 obj1 失败");
                     }          
                 }else{
                    System.out.println(new Date().toString() + "LockB 锁 obj2 失败");
                 }
                unlock.a1.release(); // 释放
                unlock.a2.release();
                Thread.sleep(1000); // 马上进行尝试,现实情况下do something是不确定的 
            }
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        }
        
    }

    进程间协调-存款取款轮换 - 针对synchronized关键字,因为存在同步监视器监视account

    package jianzhioffer;
    
    import java.util.concurrent.locks.ReentrantLock;
    
    class Account {
        public String accountNo;
        public double balance;
        //可重入锁
        public boolean flag=false;//是否有人存钱
        public Account(String accountNo, double balance) {
            this.accountNo = accountNo;
            this.balance = balance;
        }
    
        public int hashcode() {
            return accountNo.hashCode();
        }
    
        public boolean equals(Object obj) {
            if (obj != null && obj.getClass() == Account.class) {
                Account target = (Account) obj;
                return target.accountNo.equals(accountNo);
            }
            return false;
        }
    
        public synchronized  void draw(double drawAmount) throws InterruptedException {
            
            try {
                if(!flag){
                    //没人存钱,等待
                    wait();
                }else{
                    System.out.println(Thread.currentThread().getName()+"取钱:"+drawAmount);
                    balance-=drawAmount;
                    System.out.println("余额为:" + balance);
                    flag=false;//转给存款
                    notifyAll();
                }
                
            } catch(Exception e){
    
            }
        }
        public synchronized  void deposit(double drawAmount) throws InterruptedException {
            try{
                if(flag){
                    wait();
                }else{
                    System.out.println(Thread.currentThread().getName()+"存钱 "+drawAmount);
                    balance=balance+drawAmount;
                    System.out.println("账户余额为"+balance);
                    flag=true;
                    notifyAll();
    
    
                }
            }catch(Exception e){
                e.printStackTrace();
    
            }
        }
    }
    
    class DrawThread extends Thread {
        public Account account;
        public double drawAmount;
    
        public DrawThread(String name, Account account, double drawAmount) {
            super(name);
            this.account = account;
            this.drawAmount = drawAmount;
        }
    
        public void run() {
            try{
            
            for(int i=0;i<100;i++){
                account.draw(drawAmount);
            }
        }catch(Exception e){
            e.printStackTrace();
    
        }
        }
    }
    
    
    class Deposit extends Thread {
        public Account account;
        public double drawAmount;
    
        public Deposit(String name, Account account, double drawAmount) {
            super(name);
            this.account = account;
            this.drawAmount = drawAmount;
        }
    
        public void run() {
            try{
            
            for(int i=0;i<100;i++){
                account.deposit(drawAmount);
            }
        }catch(Exception e){
            e.printStackTrace();
    
        }
        }
    }
    public class testSynchronize1 extends Thread{
        public static void main(String[] args) throws InterruptedException {
            Account acc=new Account("1234567", 0);
            new DrawThread("取款者",acc,800).start();
            // Thread.sleep(100);
            new Deposit("存款者甲",acc,800).start();
            new Deposit("存款者乙",acc,800).start();
            new Deposit("存款者丙",acc,800).start();
    
    
        }
        
    }

    使用条件变量控制协调 - 针对用 Lock的因为没有监视器-Condition将wait,notify-变成await,signal

    package jianzhioffer;
    
    import java.util.concurrent.locks.Condition;
    import java.util.concurrent.locks.ReentrantLock;
    
    class Account {
        public final ReentrantLock lock=new ReentrantLock();
        public final Condition cond=lock.newCondition();//conditioon将wait,notify,notifyall分解成三个截然不同的方法
        public String accountNo;
        public double balance;
        //可重入锁
        public boolean flag=false;//是否有人存钱
        public Account(){}
        public Account(String accountNo, double balance) {
            this.accountNo = accountNo;
            this.balance = balance;
        }
    
        public int hashcode() {
            return accountNo.hashCode();
        }
    
        public boolean equals(Object obj) {
            if (obj != null && obj.getClass() == Account.class) {
                Account target = (Account) obj;
                return target.accountNo.equals(accountNo);
            }
            return false;
        }
    
        public  void draw(double drawAmount) throws InterruptedException {
            lock.lock();
            
            try {
                if(!flag){
                    //没人存钱,等待
                    cond.await();
                }else{
                    System.out.println(Thread.currentThread().getName()+"取钱:"+drawAmount);
                    balance-=drawAmount;
                    System.out.println("余额为:" + balance);
                    flag=false;//转给存款
                    cond.signalAll();
                }
                
            } catch(Exception e){
                e.printStackTrace();
            }finally{
                lock.unlock();
            }
        }
        public  void deposit(double drawAmount) throws InterruptedException {
            lock.lock();
            try{
                if(flag){
                    cond.await();
                }else{
                    System.out.println(Thread.currentThread().getName()+"存钱 "+drawAmount);
                    balance=balance+drawAmount;
                    System.out.println("账户余额为"+balance);
                    flag=true;
                    cond.signalAll();
    
    
                }
            }catch(Exception e){
                e.printStackTrace();
    
            }finally{
                lock.unlock();
            }
        }
    }
    
    class DrawThread extends Thread {
        public Account account;
        public double drawAmount;
    
        public DrawThread(String name, Account account, double drawAmount) {
            super(name);
            this.account = account;
            this.drawAmount = drawAmount;
        }
    
        public void run() {
            try{
            
            for(int i=0;i<10;i++){
               
                account.draw(drawAmount);
            }
        }catch(Exception e){
            e.printStackTrace();
    
        }
        }
    }
    
    
    class Deposit extends Thread {
        public Account account;
        public double drawAmount;
    
        public Deposit(String name, Account account, double drawAmount) {
            super(name);
            this.account = account;
            this.drawAmount = drawAmount;
        }
    
        public void run() {
            try{
            
            for(int i=0;i<10;i++){
                account.deposit(drawAmount);
            }
        }catch(Exception e){
            e.printStackTrace();
    
        }
        }
    }
    public class testSynchronize1 extends Thread{
        public static void main(String[] args) throws InterruptedException {
            Account acc=new Account("1234567", 0);
            new DrawThread("取款者",acc,800).start();
            // Thread.sleep(100);
            new Deposit("存款者甲",acc,800).start();
            new Deposit("存款者乙",acc,800).start();
            new Deposit("存款者丙",acc,800).start();
    
    
        }
        
    }

    使用管道流通讯PipedInputStream,PipedReader,Pipe.SinkChannel

    package jianzhioffer;
    
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.PipedReader;
    import java.io.PipedWriter;
    
    class ReaderThread extends Thread{
        public PipedReader pr;//来源
        public BufferedReader br;
        public ReaderThread(){}
        public ReaderThread(PipedReader pr){
            this.pr=pr;
            this.br=new  BufferedReader(pr);//读到buffer
        }
        public void run(){
            String buf=null;
            try{
                while((buf=br.readLine())!=null){
                    System.out.println(buf);//输出
                }
            }catch(Exception e){
                e.printStackTrace();
            }finally{
                try{
                    {
                        if(br!=null){
                            br.close();
                        }
                    }
                }catch(Exception e){
                    e.printStackTrace();
                }
            }
    
        }
        
    }
    class WiterThread extends Thread{
        String []books=new String[]{//输入
            "aaaaaaaaa",
            "bbbbbbbbbb",
            "ccccc",
            "ddddddd"
        };
        public PipedWriter pw;
        public WiterThread(){};
        public WiterThread(PipedWriter pw){
            this.pw=pw;
    
        }
        public void run(){
            try{
                for(int i=0;i<100;i++){
                    System.out.println(i);
                    pw.write(books[i%4]+"
    ");//读到pw
                }
            }catch(Exception e){
                e.printStackTrace();
    
            }finally{
                try{
                    if(pw!=null){
                        pw.close();
                    }
                }catch(IOException e){
                    e.printStackTrace();
    
                }
            }
        }
    
    }
    public class PipeCommunication {
        public static void main(String[] args) {
            PipedWriter pw=null;
            PipedReader pr=null;
            try{
            pw=new PipedWriter();
            pr=new PipedReader();
            
            pw.connect(pr);//输入输出连接
            new WiterThread(pw).start();
            new ReaderThread(pr).start();
            }catch(Exception e){
                e.printStackTrace();
    
            }
    
        }
        
    }

    线程池:

    程序将一个runnable对象传给线程池,线程池就启动一条线程执行这个线程的run,执行完该线程不会死亡,回到新城吃成为空闲,等待下一个runnable

    存在原因:启动一个线程成本高,涉及与操作系统的交互,在这种情况下,使用线程池可以提高性能,另外可以有效控制并发线程数量,低于抖动阈值

    Ececutors工厂用来创建线程池

    new CachedThreadPool() - 有缓存功能,,线程被缓存在线程池

    new FixedThreadPool(int x):固定线程数量,可重用

    new SingleThreadPool(),单独一个线程

    new ScheduleThreadPool(int x),指定延迟后执行任务

    new SingleThreadScheduleExcecutor(int x),指定延迟后执行任务,单个线程

    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    
    class TestThread implements Runnable{
        public void run(){
            for(int i=0;i<100;i++){
                System.out.println(Thread.currentThread().getName()+"的值为:"+i);
            }
        }
    }
    
    
    public class ThreadPoolTest {
        public static void main(String[] args) {
            ExecutorService pool=Executors.newFixedThreadPool(6);
            pool.submit(new TestThread());
            pool.submit(new TestThread());
            //shutdown执行完了shutdown,
            //shutdownNow,试图立刻结束,全部杀死
            pool.shutdownNow();
    
        }
    
        
    }
    package jianzhioffer;


    class Account{
        public  String accountNo;
        public double balance;
        public Account(String accountNo,double balance){
            this.accountNo=accountNo;
            this.balance=balance;
        }
        public int hashcode(){
            return accountNo.hashCode();
        }
        public boolean equals(Object obj){
            if(obj!=null&&obj.getClass()==Account.class){
                Account target=(Account)obj;
                return target.accountNo.equals(accountNo);
            }
            return false;
        }
    }
    class DrawThread extends Thread{
        public Account account;
        public double drawAmount;
        public DrawThread(String name,Account account,double drawAmount){
            super(name);
            this.account=account;
            this.drawAmount=drawAmount;
        }
        public void run(){
            //1.同步代码块,account是同步监视器,在执行这个代码块之前锁定account
            synchronized(account){
            if(account.balance>=drawAmount){
                System.out.println("吐钱成功,吐出钞票:"+drawAmount);
                try{
                    Thread.sleep(1);
                }catch(InterruptedException ex){
                    ex.printStackTrace();
                }
                account.balance=account.balance-drawAmount;
                System.out.println("余额为:"+account.balance);
            }else{
                System.out.println(getName()+"取钱失败,余额不足");
            }
        }
            //同步代码块结束,释放同步锁(同步监视器account)
        }
    }
    public class testSynchronize1 extends Thread{
        public static void main(String[] argsthrows InterruptedException {
            Account acc=new Account("1234567"1000);
            new DrawThread("甲",acc,800).start();
            // Thread.sleep(100);
            new DrawThread("已",acc,800).start();
            //出现不安全问题
            /**
             * 吐钱成功,吐出钞票:800.0
               吐钱成功,吐出钞票:800.0
               余额为:200.0
               余额为:-600.0
             */



        }
        
    }
  • 相关阅读:
    1.Spring Framework 5.0 入门篇
    Spring,Spring MVC,Spring Boot 三者比较
    函数式编程:函数作为变量和函数的计算结果
    函数式编程:面向可复用的map和pipeline机制的编程语言
    异常处理的本质
    Error handling in Swift does not involve stack unwinding. What does it mean?
    函数式编程介绍
    pure funtion
    函数式编程与命令式编程
    命令式编程是面向计算机硬件的抽象
  • 原文地址:https://www.cnblogs.com/jieyi/p/14311184.html
Copyright © 2011-2022 走看看