Thread本质上也是实现了Runnable接口的一个实例,他代表一个线程的实例,并且,启动线程的唯一方法就是通过Thread类的start()方法。start()方法是一个本地方法,他将启动一个新线程,并执行 run()方法(只有通过start()方法调用的run()方法才能真正的起到异步的作用)。
**小提示**start()方法被调用后并不是立刻执行多线程的代码,而是使得该线程变为可运行状态,什么时候运行多线程代码是由操作系统决定的。(就绪,运行,挂起,结束)
小提示创建Thread对象,用事先Runnable接口的对象作为参数实例化改Thread对象。
synchronized关键字主要有两种用法:
1.synchronized申明方法:public synchronized void xxx();
2.synchronized代码块:synchronized(obj){}
wait()方法表示放弃当前对资源的占有权并且释放对象锁进入等待状态,一直到有人通知。
notify()方法表示当前的线程已经放弃对资源的占有,通知等待的线程来获得对资源的占有权。然后运行wait()后面的语句。被唤醒的线程依旧阻塞在wait()中直到获得对象的锁
重点内容:notify()方法放弃对资源的占用但是并没有释放对象锁
**“`
public class Consumer implements Runnable {
@Override
public synchronized void run() {
// TODO Auto-generated method stub
int count = 10;
while(count > 0) {
synchronized (Test. obj) {
System. out.print( "B");
count --;
Test. obj.notify(); // 主动释放对象资源
try {
Test. obj.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
public class Produce implements Runnable {
@Override
public void run() {
// TODO Auto-generated method stub
int count = 10;
while(count > 0) {
synchronized (Test. obj) {
//System.out.print("count = " + count);
System. out.print( "A");
count --;
Test. obj.notify();
try {
Test. obj.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
测试类如下:
public class Test {
public static final Object obj = new Object();
public static void main(String[] args) {
new Thread( new Produce()).start();
new Thread( new Consumer()).start();
}
}
“`**
**`除了wait()和notify()协作完成线程同步之外,使用Lock也可以完成同样的目的。
ReentrantLock 与synchronized有相同的并发性和内存语义,还包含了中断锁等候和定时锁等候,意味着线程A如果先获得了对象obj的锁,那么线程B可以在等待指定时间内依然无法获取锁,那么就会自动放弃该锁。
但是由于synchronized是在JVM层面实现的,因此系统可以监控锁的释放与否,而ReentrantLock使用代码实现的,系统无法自动释放锁,需要在代码中finally子句中显式释放锁lock.unlock();
同样的例子,使用lock 如何实现呢?
public class Consumer implements Runnable {
private Lock lock;
public Consumer(Lock lock) {
this. lock = lock;
}
@Override
public void run() {
// TODO Auto-generated method stub
int count = 10;
while( count > 0 ) {
try {
lock.lock();
count --;
System. out.print( "B");
} finally {
lock.unlock(); //主动释放锁
try {
Thread. sleep(91L);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
public class Producer implements Runnable{
private Lock lock;
public Producer(Lock lock) {
this. lock = lock;
}
@Override
public void run() {
// TODO Auto-generated method stub
int count = 10;
while (count > 0) {
try {
lock.lock();
count --;
System. out.print( "A");
} finally {
lock.unlock();
try {
Thread. sleep(90L);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
调用代码:
public class Test {
public static void main(String[] args) {
Lock lock = new ReentrantLock();
Consumer consumer = new Consumer(lock);
Producer producer = new Producer(lock);
new Thread(consumer).start();
new Thread( producer).start();
}
}
使用建议:
在并发量比较小的情况下,使用synchronized是个不错的选择,但是在并发量比较高的情况下,其性能下降很严重,此时ReentrantLock是个不错的方案。`**