线程中部分方法的整理

等待(wait)和通知(notify)

这两个方法都是Object 类的方法,用于多线程 ,必须用在synchronize语句中,比如在线程A中,调用了obj.wait()方法,那么线程A就会停止继续执行(释放锁),转为等待状态,线程A会一直等到其他线程调用obj.notify()方法为止。
在多线程中,,因为系统可能运行多个线程同时等待某一个对象。当object.notify()方法被调用时,它就会从这个队列中随机选择一个线程,并将其唤醒。并不是谁先等待就谁先唤醒
除notify()方法外,Object独享还有一个nofiyAll()方法,它和notify()方法的功能类似,不同的是,它会唤醒在这个等待队列中所有等待的线程,而不是随机选择一个。

package com.example.demo.demo.xiancheng;

import java.util.Objects;

public class SecondThread {
       static Object object = new Object();
    public static class T1 extends Thread {
        @Override
        public void run() {
            synchronized (object) {
                System.out.println(System.currentTimeMillis()+"T1 start");
                try {
                    System.out.println(System.currentTimeMillis()+"T1 wait");
                    object.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(System.currentTimeMillis()+"T1 end");
            }
        }

    }
    public static class T2 extends Thread{
        @Override
        public void run() {
            synchronized (object){
                System.out.println(System.currentTimeMillis()+"T2 start");
                object.notify();
                System.out.println(System.currentTimeMillis()+"T2 end");
                try {
                    Thread.sleep(200);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static void main(String[] args) {
        new T1().start();
        new T2().start();
    }
}

1590418493678T1 start
1590418493678T1 wait
1590418493679T2 start
1590418493679T2 end
1590418493880T1 end

T2调用notify方法之后,T1并不能立即继续执行,而是要等待T2释放object投递锁之后,T1重新成功获取锁后,才能继续执行。
注意:Object.wait()方法和Thread.sleeep()方法都可以让现场等待若干时间。除wait()方法可以被唤醒外,另外一个主要的区别就是wait()方法会释放目标对象的锁,而Thread.sleep()方法不会释放锁。

join()

很多时候,一个线程的输入可能非常依赖于另外一个或者多个线程的输出,此时,这个线程就需要等待依赖的线程执行完毕,才能继续执行。jdk提供了join()

.join()方法只会使主线程进入等待池并等待t线程执行完毕后才会被唤醒。并不影响同一时刻处在运行状态的其他线程

以例子来


public class TestJoin {
 
	public static void main(String[] args) throws InterruptedException {
		// TODO Auto-generated method stub
		ThreadTest t1=new ThreadTest("A");
		ThreadTest t2=new ThreadTest("B");
		t1.start();
		t1.join();
		t2.start();
	}
}

class ThreadTest extends Thread {
	private String name;
	public ThreadTest(String name){
		this.name=name;
	}
	public void run(){
		for(int i=1;i<=5;i++){
				System.out.println(name+"-"+i);
		}		
	}
}

输出结果

A-1
A-2
A-3
A-4
A-5
B-1
B-2
B-3
B-4
B-5

t1.join();等待A进程执行完,B才能执行
但是将如果t1.join()放在t2.start()之后的话,仍然会是交替执行,原因是停止的是当前主线程在这是main,t1,t2是类似于子线程。
join()的源码。

    /**
     * Waits for this thread to die.
     *
     * <p> An invocation of this method behaves in exactly the same
     * way as the invocation
     *
     * <blockquote>
     * {@linkplain #join(long) join}{@code (0)}
     * </blockquote>
     *
     * @throws  InterruptedException
     *          if any thread has interrupted the current thread. The
     *          <i>interrupted status</i> of the current thread is
     *          cleared when this exception is thrown.
     */
    public final void join() throws InterruptedException {
        join(0);            //join()等同于join(0)
    }
    /**
     * Waits at most {@code millis} milliseconds for this thread to
     * die. A timeout of {@code 0} means to wait forever.
     *
     * <p> This implementation uses a loop of {@code this.wait} calls
     * conditioned on {@code this.isAlive}. As a thread terminates the
     * {@code this.notifyAll} method is invoked. It is recommended that
     * applications not use {@code wait}, {@code notify}, or
     * {@code notifyAll} on {@code Thread} instances.
     *
     * @param  millis
     *         the time to wait in milliseconds
     *
     * @throws  IllegalArgumentException
     *          if the value of {@code millis} is negative
     *
     * @throws  InterruptedException
     *          if any thread has interrupted the current thread. The
     *          <i>interrupted status</i> of the current thread is
     *          cleared when this exception is thrown.
     */
    public final synchronized void join(long millis) throws InterruptedException {
        long base = System.currentTimeMillis();
        long now = 0;
 
        if (millis < 0) {
            throw new IllegalArgumentException("timeout value is negative");
        }
 
        if (millis == 0) {
            while (isAlive()) {
                wait(0);           //join(0)等同于wait(0),即wait无限时间直到被notify
            }
        } else {
            while (isAlive()) {
                long delay = millis - now;
                if (delay <= 0) {
                    break;
                }
                wait(delay);
                now = System.currentTimeMillis() - base;
            }
        }
    }

可以看出join()方法的底层是利用wait()方法实现的。可以看出,join方法是一个同步方法,当主线程调用t1.join()方法时,主线程先获得了t1对象的锁,随后进入方法(wait(0)wait无限时间直到被notify),调用了t1对象的wait()方法,使主线程进入了t1对象的等待池,此时,A线程则还在执行,并且随后的t2.start()还没被执行,因此,B线程也还没开始。等到A线程执行完毕之后,主线程继续执行,走到了t2.start(),B线程才会开始执行。

:join源码中,只会调用wait方法,并没有在结束时调用notify,这是因为线程在死亡的时候会自动调用自身的notifyAll方法,来释放所有的资源和锁。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值