练习一:银行有一个账户。有两个储户分别向同一个账户存3000元,每次存1000存3次。每次存完打印账户余额。
分析:
(1)两个储户对应两个线程
(2) 共享数据:账户余额
(3) 存在线程安全问题 : 考虑使用同步机制来解决
代码实现:
public class AcctTest {
public static void main(String[] args) {
Account acct=new Account(0);
Customer c1=new Customer(acct);
Customer c2=new Customer(acct);
c1.setName("储户1");
c2.setName("储户2");
c1.start();
c2.start();
}
}
class Account{
private double balance;
public Account(double balance){
this.balance=balance;
}
public synchronized void deposit(double amount){
if(amount>0){
balance+=amount;
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"存钱成功:余额为"+balance);
}
}
}
class Customer extends Thread{
private Account acct=new Account(0);
public Customer(Account acct){
this.acct=acct;
}
@Override
public void run() {
for(int i=0;i<3;i++){
acct.deposit(1000);
}
}
}
练习二:使用两个线程打印1-100,线程1,线程2交替打印
分析:
(1)两个线程可能存在线程安全问题 : 考虑使用同步机制来解决
(2)两个线程的交替实现需要配合使用wait()和notify()
代码实现:
public class CommunicationTest {
public static void main(String[] args) {
Number num=new Number();
Thread t1=new Thread(num);
Thread t2=new Thread(num);
t1.setName("线程1");
t2.setName("线程2");
t1.start();
t2.start();
}
}
class Number implements Runnable{
private int number=1;
private Object obj=new Object();
@Override
public void run() {
while(true){
synchronized (obj){
obj.notify();
if(number<=100){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+":"+number);
number++;
try {
//使得调用如下wait()方法的线程进入阻塞状态
obj.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}else{
break;
}
}
}
}
}
练习三:生产者消费者例题
生产者 Productor 将产品交给店员 ( Clerk),而消费者 ( 从店员处取走产品,店员一次只能持有固定数量的产品,比如:20 ),如果生产者试图生产更多的产品,店员会叫生产者停一下,如果店中有空位放产品了再通知生产者继续生产;如果店中没有产品了,店员会告诉消费者等一下,如果店中有产品了再通知消费者来取走产品。
分析:
1.是否是多线程问题? 是 生产者线程和消费者线程 2.是否有共享数据? 是 店员(或产品) 3.如何解决线程安全问题? 三种方法 4.是否涉及线程的通信? 是 需要使用wait()和notify()
代码实现:
public class ProductTest {
public static void main(String[] args) {
Clerk clerk=new Clerk();
Producer p1=new Producer(clerk);
p1.setName("生产者1");
Customer c1=new Customer(clerk);
c1.setName("消费者1");
Customer c2=new Customer(clerk);
c2.setName("消费者2");
p1.start();
c1.start();
c2.start();
}
}
//
class Clerk{
private int productCount=0;
//生产产品
public synchronized void produceProduct(){
if(productCount<20){
productCount++;
System.out.println(Thread.currentThread().getName()+":开始生产第"+productCount+"个产品");
notify();
}else{
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
//消费产品
public synchronized void consumeProduct(){
if(productCount>0){
System.out.println(Thread.currentThread().getName()+":开始消费第"+productCount+"个产品");
productCount--;
notify();
}else{
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
//生产者
class Producer extends Thread{
private Clerk clerk;
public Producer(Clerk clerk){
this.clerk=clerk;
}
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+":开始生产产品......");
while (true){
clerk.produceProduct();
}
}
}
//消费者
class Customer extends Thread {
private Clerk clerk;
public Customer(Clerk clerk){
this.clerk=clerk;
}
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+":开始消费产品......");
while (true){
clerk.consumeProduct();
}
}
}