使用三个线程出售10张票:
package com.sun.test;
class MyThread extends Thread {
private int ticket=10;
@Override
public void run() {
for(int i=0;i<10;i++) {
if(this.ticket>0) {
System.out.println(Thread.currentThread().getName()+"正在出售倒数第"+this.ticket-- +"张票!");
}
}
}
}
public class Test {
public static void main(String[] args) throws InterruptedException {
// 创建了三个线程对象,这三个线程对象共享一个线程主体类对象
Thread thA = new MyThread();
Thread thB = new MyThread();
Thread thC = new MyThread();
thA.start();
thB.start();
thC.start();
}
}
此时发现了三个线程卖了30张票,但是要求只卖十张,出现这个问题的原因是什么呢?问题的原因是每个线程都有自己独立十张票,没有实现三个线程共享一个数据的要求,怎么去解决这个问题呢?可以将ticket声明为静态变量。静态变量保存在方法区(方法区在jdk1.8之前是永久代实现的,在jdk1.8开始就是元空间实现,取消了永久代),保存在方法区中的数据是线程共享的。
将ticket声明为静态变量:
private static int ticket = 10;
证明了static声明的变量是保存在方法区,方法区的数据是线程共享的。多个线程共享一个静态数据。如果不使用这种方式还可以使用使用Runnable接口的方式实现。
实现Runnable接口:
package com.sun.test;
class RunThread implements Runnable{
private int ticket=10;
@Override
public void run() {
for(int i=0;i<10;i++) {
if(this.ticket>0) {
System.out.println(Thread.currentThread().getName()+"正在出售倒数第"+this.ticket-- +"张票!");
}
}
}
}
public class Test {
public static void main(String[] args) throws InterruptedException {
//创建一个线程主体类对象
Runnable rn=new RunThread();
// 创建了三个线程对象,这三个线程对象共享一个线程主体类对象
Thread thA = new Thread(rn);
Thread thB = new Thread(rn);
Thread thC = new Thread(rn);;
thA.start();
thB.start();
thC.start();
}
}
之前共享的是一个静态变量,现在三个线程共享的是同一个线程主体类对象。一般使用比较多的是实现Runnable接口,很方便的实现了数据的共享。
面试题:说明Thread和Runnable的区别和联系?
Thread:
具有单继承局限
不方便实现数据的共享(也可以,但是看起来很怪异)
Runnable接口:
不具有单继承局限
方便实现数据的共享(共享的是同一个线程主体类对象)
Thread实现了Runnable接口:
使用Runnable接口实现的线程启动需要借助Thread类的start()方法启动