java多线程基础练习及分析

时间:2022-12-29 22:53:53

练习1:同步代码段synchronized(this)
public class SyncThread implements Runnable {


private static int count;

public SyncThread() {
count = 0;
}

@Override
public void run() {
/**
* synchronized(this)代码段,相当于同步锁定该方法的对象,等同于synchronized修饰非static方法
*/
synchronized(this) {
for(int i=5;i>0;i--) {
System.out.println(Thread.currentThread().getName()+ ":" + (count++));
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}

public static void main(String[] args) {
SyncThread st = new SyncThread();

Thread t1 = new Thread(st, "A");
Thread t2 = new Thread(st, "B");
t1.start();
t2.start();
}

}
分析:同步锁加在了this上,当持有该对象的多个线程同时执行到syncronized代码段时,此时锁机制就会发挥作用,保证同一时刻只能有一个线程执行同步代码段。
如果是两个线程持有的是两个不同的对象,此时this就分别是两个不同的对象,就不受限制了,如下所示:
public static void main(String[] args) {
SyncThread st1 = new SyncThread();
SyncThread st2 = new SyncThread();

Thread t1 = new Thread(st1, "A");
Thread t2 = new Thread(st2, "B");
t1.start();
t2.start();
}
练习2:同步代码段synchronized(A.class)和synchronized修饰static方法
/**
 * 设计场景,希望count的值在一个方法中先加1,再减1,最后不变。
 * @author andy
 *
 */
public class SyncThread2 implements Runnable {


private static int count;

public SyncThread2() {
count = 0;
}

public static void addCount() {
System.out.println(Thread.currentThread().getName()+ ":" + (++count));
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+ ":" + (--count));
}

/**
* synchronized修饰static方法时,相当于同步锁定该类的class,这样该类的所有对象都持有该方法的锁
*/
public static synchronized void addCount2() {
System.out.println(Thread.currentThread().getName()+ ":" + (++count));
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+ ":" + (--count));
}

/**
* synchronized修饰class时,相当于同步锁定该类的class,这样该类的所有对象都持有该方法的锁
*/
public static void addCount3() {
synchronized(SyncThread2.class) {
System.out.println(Thread.currentThread().getName()+ ":" + (++count));
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+ ":" + (--count));
}
}

@Override
public void run() {
for(int i=5;i>0;i--) {
//非同步安全,在多线程并发环境中无法完成每个方法执行后count的值不变
addCount();
//同步安全
//addCount2();
}
}

public static void main(String[] args) {
SyncThread2 st1 = new SyncThread2();
SyncThread2 st2 = new SyncThread2();

Thread t1 = new Thread(st1, "A");
Thread t2 = new Thread(st2, "B");
t1.start();
t2.start();
}
}


练习3:综合练习,模拟银行并发存款取款
/**
 * 个人银行账户
 * @author alex
 *
 */
public class Account {
    private String accountNo;
    private double balance;
 
    private boolean flag = false;
 
    public Account(String _accountNo, double _balance) {
        this.accountNo = _accountNo;
        this.balance = _balance;
    }
 
    public String getAccountNo() {
        return accountNo;
    }
 
    public void setAccountNo(String accountNo) {
        this.accountNo = accountNo;
    }
 
    public double getBalance() {
        return balance;
    }
    
    /**
     * synchronized修饰非static方法,相当于同步锁定该方法的对象,等同于synchronized(this)代码段
     * @param drawBalance
     */
    public synchronized void drawBalance(double drawBalance) {
        if (flag) {
            if (balance > drawBalance) {
                System.out.println(Thread.currentThread().getName() + "取钱成功,正在吐钞:" + drawBalance);
                balance -= drawBalance;
                flag = false;
                this.notifyAll();
                System.out.println(Thread.currentThread().getName() + "余额为:" + getBalance());
            } else {
                System.out.println(Thread.currentThread().getName() + "取钱失败,余额不足");
            }
        } else {
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
 
    /**
     * synchronized修饰非static方法,相当于同步锁定该方法的对象,等同于synchronized(this)代码段
     * @param depositBalance
     */
    public synchronized void deposit(double depositBalance) {
        if (flag) {
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        } else {
            System.out.println(Thread.currentThread().getName() + " 存款:" + depositBalance);
            this.balance += depositBalance;
            flag = true;
            this.notifyAll();
            System.out.println(Thread.currentThread().getName() + "余额为:" + getBalance());
        }
    }
}




/**
 * 存钱线程
 * @author andy
 *
 */
public class StorerThread implements Runnable {
    private Account account;
    private double depositBalance;
 
    public Account getAccount() {
        return account;
    }
 
    public void setAccount(Account account) {
        this.account = account;
    }
 
    public double getDepositBalance() {
        return depositBalance;
    }
 
    public void setDepositBalance(double depositBalance) {
        this.depositBalance = depositBalance;
    }
 
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            account.deposit(depositBalance);
        }
    }
}




/**
 * 取钱线程
 * @author andy
 *
 */
public class FetcherThread implements Runnable {
    private Account account;
    private double drawBalance;
 
    public Account getAccount() {
        return account;
    }
 
    public void setAccount(Account account) {
        this.account = account;
    }
 
    public double getDrawBalance() {
        return drawBalance;
    }
 
    public void setDrawBalance(double drawBalance) {
        this.drawBalance = drawBalance;
    }
 
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            account.drawBalance(drawBalance);
        }
    }
}




/**
 * 模拟银行账户并发存款取款
 * @author alex
 *
 */
public class AccountSyncTest {


public static void main(String[] args) {
Account acc = new Account("001", 1000);
 
        OfferThread mt1 = new OfferThread();
        mt1.setAccount(acc);
        mt1.setDrawBalance(20);
 
        Thread t1 = new Thread(mt1, "取钱者1");
        Thread t2 = new Thread(mt1, "取钱者2");
 
        FetchThread mt2 = new FetchThread();
        mt2.setAccount(acc);
        mt2.setDepositBalance(20);
 
        Thread t3 = new Thread(mt2, "存钱者1");
        Thread t4 = new Thread(mt2, "存钱者2");
 
        t1.start();
        t2.start();
        t3.start();
        t4.start();
}
}


练习4:线程几种状态切换