为什么用Runnable接口,好处如下:
1. 实现 Runnable 接口 可以避免Thread单继承的问题 ,给你这个Runnable 再继承一次的机会
2. Runnable接口 可以实现变量共享 ,如下卖票的例子 tickets 变量全局共享
public class SellTickets implements Runnable{
private int tickets = 5;
Object obj = new Object();
public SellTickets() {
// TODO Auto-generated constructor stub
}
public void run() {
// TODO Auto-generated method stub
while(true){
synchronized (obj) {
if(tickets>0){ <span style="color:#FF0000;">//共享资源的判断都要放在同步块里</span>
--tickets;
System.out.println(Thread.currentThread().getName() +"there were " + tickets +" left");
obj.notify();
try {
obj.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//System.out.println(Thread.currentThread().getName() +" whoami");
}else{
obj.notify(); <span style="color:#FF0000;">// 注意这边一定要 notify,不然倒数第二个线程 在wait后没有线程唤醒它</span>
break;
}
}
}
}
public static void main(String[] args) {
Runnable st1 = new SellTickets();
Thread t1 = new Thread(st1);
Thread t2 = new Thread(st1);
Thread t3 = new Thread(st1);
t1.start();
t2.start();
t3.start();
}
}
output:
Thread-0there were 4 left
Thread-2there were 3 left
Thread-1there were 2 left
Thread-2there were 1 left
Thread-0there were 0 left
生产者消费者代码
public class ProducerConsumerTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
BreadStore bstore = new BreadStore();
Runnable p = new Producer(bstore);
Runnable c = new Consumer(bstore);
Thread t1 = new Thread(p);
Thread t2 = new Thread(p);
Thread t3 = new Thread(p);
t1.start();
t2.start();
t3.start();
Thread c1 = new Thread(c);
Thread c2 = new Thread(c);
Thread c3 = new Thread(c);
c1.start();
c2.start();
c3.start();
}
}
class Producer implements Runnable{
private BreadStore breadstore = null;
public Producer(BreadStore breadstore){
this.breadstore = breadstore;
}
void produce(){
String tname = Thread.currentThread().getName();
breadstore.produce(tname);
}
public void run() {
while(true){
try {
Thread.sleep(1000); //sleep 可以让cpu 分配资源可以其他线程,而不用 sync wait notifys
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
produce();
}
}
}
class Consumer implements Runnable{
private BreadStore breadstore = null;
public Consumer(BreadStore breadstore){
this.breadstore = breadstore;
}
void get(String tname){
breadstore.get(tname);
}
public void run() {
while(true){
try {
Thread.sleep(1000); //模拟生产 或者消费时间 时间可以随机
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
String tname = Thread.currentThread().getName();
get(tname);
}
}
}
class BreadStore{
int size = 0;
final int capability = 30;
synchronized void produce(String tname){
if (size < capability){
System.out.println(tname + "just produce a bread: " + ++size + " loaves of bread remained");
}else {
System.out.println(tname + "we have enough breads");
}
}
synchronized void get(String tname){
if(size > 0){
System.out.println(tname + "just get a bread:" + --size + " loaves of bread remained");
}else{
System.out.println(tname + "there is no bread left");
}
}
}
_________________________________________________________