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]+"\n");//读到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
         */



    }
    
}