上一篇线程主要是线程的基本使用方法,这一篇文章讲解线程之间的同步和通信。
线程的同步和通信是一个重点。
很多书上讲解线程之间的同步时,都使用了一个售票系统。
首先我们用上一篇写知识点,模拟一个售票系统。
public class ThreadDemo2 implements Runnable{
private int i=100;
@Override
public void run() {
while(i>0){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("售出第"+(i--)+"张票"+"-----"+Thread.currentThread().getName());
}
}
public static void main(String[] args) {
ThreadDemo2 runableDemo=new ThreadDemo2();
Thread th=new Thread(runableDemo,"窗口一");
Thread th1=new Thread(runableDemo,"窗口二");
System.out.println("开始买票了");
th.start();
th1.start();
}
看一下效果图:
会发现,窗口一和窗口二都买出了第98张票。这样是不行啊,所以只能使用同步了。
接下来介绍一个关键字,synchronized关键字,实现同步代码块。
public class ThreadDemo2 implements Runnable{
private int i=100;
@Override
public void run() {
synchronized (this) {//同步代码块
while(i>0){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("售出第"+(i--)+"张票"+"-----"+Thread.currentThread().getName());
}
}
}
public static void main(String[] args) {
ThreadDemo2 runableDemo=new ThreadDemo2();
Thread th=new Thread(runableDemo,"窗口一");
Thread th1=new Thread(runableDemo,"窗口二");
System.out.println("开始买票了");
th.start();
th1.start();
}
}
效果图:
我们会发现,售出的票没有了重复。
加一个题外话,今天我去亚信面试,就是一个校招,做了一份题,里面有个线程题,结果是什么?
new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
System.out.println("haha");
}
}).run();
我当时没仔细看,说,没有start(),所以没有任何结果。还是年轻,全部都是套路,他并没有调用start()方法,但是调用了run()方法,这个代码的意思就是说,一个Thread的子类对象,调用run()方法,输出的是字符串"haha",这样run()方法就相当于是一个普通的方法,并没有涉及到线程,因为这个线程并没有开启。
synchronized关键字还可以用在方法上
public class ThreadDemo2 implements Runnable{
private int i=100;
@Override
public void run() {
this.haha();
}
public synchronized void haha(){
while(i>0){
try {
Thread.sleep(50);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("售出第"+(i--)+"张票"+"-----"+Thread.currentThread().getName());
}
}
public static void main(String[] args) {
ThreadDemo2 runableDemo=new ThreadDemo2();
Thread th=new Thread(runableDemo,"窗口一");
Thread th1=new Thread(runableDemo,"窗口二");
System.out.println("开始买票了");
th.start();
th1.start();
}
}
和上面是有synchronized实现同步代码块的效果一样。
大家会发现,使用synchronized实现的方法或者是同步代码块,只要一个线程占用其同步锁,其他线程是无法获得运行权的。这就是我们的效果,每次只有一个线程进行买票操作。
同步锁:
lock(),实现加锁操作,unlock()释放同步锁。
public class ThreadDemo2 implements Runnable{
private ReentrantLock lock=new ReentrantLock();
private int i=100;
@Override
public void run() {
while(i>1){
lock.lock();
try {
Thread.sleep(50);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("售出第"+(i--)+"张票"+"-----"+Thread.currentThread().getName());
lock.unlock();
}
}
public static void main(String[] args) {
ThreadDemo2 runableDemo=new ThreadDemo2();
Thread th=new Thread(runableDemo,"窗口一");
Thread th1=new Thread(runableDemo,"窗口二");
System.out.println("开始买票了");
th.start();
th1.start();
}
}
效果图:既有线程一,又有线程二
——线程之间通信,简单介绍
线程之间的通信的方法,全部定义在Object类里面
public class Object {
private static native void registerNatives();
static {
registerNatives();
}
public final native Class<?> getClass();
public native int hashCode();
public boolean equals(Object obj) {
return (this == obj);
}
protected native Object clone() throws CloneNotSupportedException;
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
public final native void notify();
public final native void notifyAll();
public final native void wait(long timeout) throws InterruptedException;
public final void wait(long timeout, int nanos) throws InterruptedException {
if (timeout < 0) {
throw new IllegalArgumentException("timeout value is negative");
}
if (nanos < 0 || nanos > 999999) {
throw new IllegalArgumentException(
"nanosecond timeout value out of range");
}
if (nanos > 0) {
timeout++;
}
wait(timeout);
}
public final void wait() throws InterruptedException {
wait(0);
}
protected void finalize() throws Throwable { }
}
通信常用的就是wait(),notify(),notifyAll()。
这是多线程的基础,下一篇应该会深入了解一下多线程。