1、sleep()方法
在指定时间内让当前正在执行的线程暂停执行,但不会释放“锁标志”。sleep()使当前线程进入阻塞状态,在指定时间内不会执行,让其他线程有机会继续执行,但它并不释放对象锁。也就是说如果有synchronized同步快,其他线程仍然不能访问共享数据。注意该方法要捕捉异常。例如有两个线程同时执行(没有synchronized)一个线程优先级为MAX_PRIORITY,另一个为MIN_PRIORITY,如果没有Sleep()方法,只有高优先级的线程执行完毕后,低优先级的线程才能够执行;但是高优先级的线程sleep(500)后,低优先级就有机会执行了。总之,sleep()可以使低优先级的线程得到执行的机会,当然也可以让同优先级、高优先级的线程有执行的机会。
2、join方法
等待该线程终止。等待调用join方法的线程结束,再继续执行。如:t.join();//主要用于等待t线程运行结束,若无此句,main则会执行完毕,导致结果不可预测。
publicclass Test {
publicstaticvoid main(String[] args) {
Thread t1 = new MyThread1();
t1.start();
for (int i = 0; i < 20; i++) {
System.out.println("主线程第" + i +"次执行!");
if (i > 2)try {
//t1线程合并到主线程中,主线程停止执行过程,转而执行t1线程,直到t1执行完毕后继续。
t1.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class MyThread1 extends Thread {
publicvoid run() {
for (int i = 0; i < 10; i++) {
System.out.println("线程1第" + i + "次执行!");
}
}
}
3、yield方法
该方法与sleep()类似,只是不能由用户指定暂停多长时间,并且yield()方法只能让同优先级的线程有执行的机会。
4、wait()方法
wait()方法使当前线程暂停执行并释放对象锁标示,让其他线程可以进入synchronized数据块,当前线程被放入对象等待池中。当调用notify()方法后,将从对象的等待池中移走一个任意的线程并放到锁标志等待池中,只有锁标志等待池中线程能够获取锁标志;如果锁标志等待池中没有线程,则notify()不起作用。
wait()方法释放锁、notify()不释放锁
notifyAll()则从对象等待池中移走所有等待那个对象的线程并放到锁标志等待池中。
使用wait和
notify实现线程之间的通信,代码如下:
public class CountDownLatchClass {
private volatile static List list = new ArrayList<>();
public void add() {
list.add("abc");
}
public int size(){
return list.size();
}
public static void main(String[] args) {
final CountDownLatchClass list = new CountDownLatchClass();
final Object lock = new Object();
Thread t1 = new Thread(new Runnable() {
public void run() {
try{
synchronized (lock) {
for(int i = 0; i<10; i++){
list.add();
System.out.println("当前线程:"+ Thread.currentThread().getName()+"添加了一个元素");
Thread.sleep(500);
if(list.size()==5){
System.out.println("已经发出通知。。。。");
lock.notify();
}
}
}
}catch(InterruptedException e){
e.printStackTrace();
}
}
},"t1");
Thread t2 = new Thread(new Runnable() {
public void run() {
synchronized (lock) {
if (list.size() != 5) {
try {
System.out.println("t2进入。。。。");
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("当前线程:"+ Thread.currentThread().getName()+"收到线程停止.....");
throw new RuntimeException();
}
}
},"t2");
t2.start();
t1.start();
}
}
输出如下:
t2进入。。。。
当前线程:t1添加了一个元素
当前线程:t1添加了一个元素
当前线程:t1添加了一个元素
当前线程:t1添加了一个元素
当前线程:t1添加了一个元素
已经发出通知。。。。
当前线程:t1添加了一个元素
当前线程:t1添加了一个元素
当前线程:t1添加了一个元素
当前线程:t1添加了一个元素
当前线程:t1添加了一个元素
当前线程:t2收到线程停止.....
Exception in thread "t2" java.lang.RuntimeException
at com.hundsun.base.thread.safeornot.CountDownLatchClass$2.run(CountDownLatchClass.java:59)
at java.lang.Thread.run(Unknown Source)
当前线程:t1添加了一个元素
当前线程:t1添加了一个元素
当前线程:t1添加了一个元素
当前线程:t1添加了一个元素
当前线程:t1添加了一个元素
已经发出通知。。。。
当前线程:t1添加了一个元素
当前线程:t1添加了一个元素
当前线程:t1添加了一个元素
当前线程:t1添加了一个元素
当前线程:t1添加了一个元素
当前线程:t2收到线程停止.....
Exception in thread "t2" java.lang.RuntimeException
at com.hundsun.base.thread.safeornot.CountDownLatchClass$2.run(CountDownLatchClass.java:59)
at java.lang.Thread.run(Unknown Source)
public class CountDownLatchClass {
private volatile static List list = new ArrayList<>();
public void add() {
list.add("abc");
}
public int size(){
return list.size();
}
public static void main(String[] args) {
final CountDownLatchClass list = new CountDownLatchClass();
//final Object lock = new Object();
final CountDownLatch countDownLatch = new CountDownLatch(1);
Thread t1 = new Thread(new Runnable() {
public void run() {
try{
//synchronized (lock) {
for(int i = 0; i<10; i++){
list.add();
System.out.println("当前线程:"+ Thread.currentThread().getName()+"添加了一个元素");
Thread.sleep(500);
if(list.size()==5){
System.out.println("已经发出通知。。。。");
countDownLatch.countDown();
//lock.notify();
}
}
//}
}catch(InterruptedException e){
e.printStackTrace();
}
}
},"t1");
Thread t2 = new Thread(new Runnable() {
public void run() {
// synchronized (lock) {
if (list.size() != 5) {
try {
System.out.println("t2进入。。。。");
// lock.wait();
countDownLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("当前线程:"+ Thread.currentThread().getName()+"收到线程停止.....");
throw new RuntimeException();
// }
}
},"t2");
t2.start();
t1.start();
}
}
输出如下:
t2进入。。。。
当前线程:t1添加了一个元素
当前线程:t1添加了一个元素
当前线程:t1添加了一个元素
当前线程:t1添加了一个元素
当前线程:t1添加了一个元素
已经发出通知。。。。
Exception in thread "t2" 当前线程:t2收到线程停止.....
当前线程:t1添加了一个元素
java.lang.RuntimeException
at com.hundsun.base.thread.safeornot.CountDownLatchClass$2.run(CountDownLatchClass.java:62)
at java.lang.Thread.run(Unknown Source)
当前线程:t1添加了一个元素
当前线程:t1添加了一个元素
当前线程:t1添加了一个元素
当前线程:t1添加了一个元素
当前线程:t1添加了一个元素
当前线程:t1添加了一个元素
当前线程:t1添加了一个元素
当前线程:t1添加了一个元素
当前线程:t1添加了一个元素
已经发出通知。。。。
Exception in thread "t2" 当前线程:t2收到线程停止.....
当前线程:t1添加了一个元素
java.lang.RuntimeException
at com.hundsun.base.thread.safeornot.CountDownLatchClass$2.run(CountDownLatchClass.java:62)
at java.lang.Thread.run(Unknown Source)
当前线程:t1添加了一个元素
当前线程:t1添加了一个元素
当前线程:t1添加了一个元素
当前线程:t1添加了一个元素
5、通过wait和notify实现queue。
如果队列中没有元素,调用take方法时,则调用此方法的线程被阻塞,直到队列中有数据被加入
实现代码如下:
public class QueueClass {
//1、需要一个装元素的集合
private final LinkedList<Object> list = new LinkedList<Object>();
//2、需要一个计数器
private final AtomicInteger count = new AtomicInteger(0);
//3、需要制定上限和下限
private final int maxSize;
private final int minSize = 0;
private final Object lock = new Object();
public QueueClass (int maxSize){
this.maxSize = maxSize;
}
public void put (Object obj) {
synchronized(lock){
while(count.get() == maxSize){
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//加入元素
list.add(obj);
//计数器加
count.getAndIncrement();
System.out.println(" 元素 " + obj + " 被添加 ");
//通知另外一个线程(唤醒)
lock.notify();
}
}
public Object take(){
Object temp = null;
synchronized (lock) {
while(count.get() == minSize){
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//移除元素
temp = list.removeFirst();
//计数器递减
count.getAndDecrement();
System.out.println(" 元素 " + temp + " 被消费 ");
//唤醒另外一个线程
lock.notify();
}
return temp;
}
public int size(){
return count.get();
}
public static void main(String[] args) throws Exception {
final QueueClass m = new QueueClass(5);
m.put("a");
m.put("b");
m.put("c");
m.put("d");
m.put("e");
System.out.println("当前元素个数:" + m.size());
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
m.put("h");
m.put("i");
}
}, "t1");
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(1000);
Object t1 = m.take();
//System.out.println("被取走的元素为:" + t1);
Thread.sleep(1000);
Object t2 = m.take();
//System.out.println("被取走的元素为:" + t2);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "t2");
t1.start();
Thread.sleep(1000);
t2.start();
}
}