本文是基于《Java多线程编程实战指南》第五章个人理解,因为第五章内容很多,因此拆成了很多文章,源码是摘抄作者的源码,源码会加上自己的理解。
读书笔记目前笔者正在更新如下, 《Java多线程编程实战指南-核心篇》,《How Tomcat Works》,再到《spring 源码》解读。
Object.wait(long)允许我们制定一个超时时间(单位为毫秒),如果被暂停的等待线程在这个时间内没有被其他线程唤醒,那么Java虚拟机会自动唤醒该线程。
不过Object.wait(long)既无返回值也不会抛出特定的异常,以便区分其返回是由于其他线程通知了当前线程还是由于等待超时。因此,使用Object.wait(long)的时候我们需要一些额外的处理。
-
-
- import java.util.Random;
-
- public class TimeoutWaitExample {
- private static final Object lock = new Object();
- private static boolean ready = false;
- protected static final Random random = new Random();
-
- public static void main(String[] args) throws InterruptedException {
- Thread t = new Thread() {
- @Override
- public void run() {
- for (;;) {
- synchronized (lock) {
- ready = random.nextInt(100) < 5 ? true : false;
- if (ready) {
- lock.notify();
- }
- }
- // 使当前线程暂停一段(随机)时间
- Tools.randomPause(500);
- }// for循环结束
- }
- };
- t.setDaemon(true);
- t.start();
- waiter(1000);
- }
-
- public static void waiter(final long timeOut) throws InterruptedException {
- if (timeOut < 0) {
- throw new IllegalArgumentException();
- }
-
- long start = System.currentTimeMillis();
- long waitTime;
- long now;
- synchronized (lock) {
- while (!ready) {
- now = System.currentTimeMillis();
- // 计算剩余等待时间
- waitTime = timeOut - (now - start);
- Debug.info("Remaining time to wait:%sms", waitTime);
- if (waitTime <= 0) {
- // 等待超时退出
- break;
- }
- lock.wait(waitTime);
- }// while循环结束
-
- if (ready) {
- // 执行目标动作
- guardedAction();
- } else {
- // 等待超时,保护条件未成立
- Debug.error("Wait timed out,unable to execution target action!");
- }
- }// 同步块结束
- }
-
- private static void guardedAction() {
- Debug.info("Take some action.");
- // ...
- }
- }
1.初始化时候,构建一个静态对象Object
2.创建了一个通知线程Thread t,是一个守护线程,并且for里面循环取值,random.nextInt,再100内取大于5的概率较大,所以是大概率位false,小概率位true
3.所以主线程是在ready=falise的while循环里,并且停止在lock.wait,主线程进入waiting状态,等待时间需要扣除一部分代码到wait语句时间。
4.最终当时间到达等待时间时间,再此判断ready条件,如果为true,则运行相应动作,如果不为true,则无法执行对应的动作。所以上述代码运行有两种结果,都有可能发生。
- import java.io.PrintStream;
- import java.text.SimpleDateFormat;
- import java.util.Date;
-
- public class Debug {
- private static ThreadLocal
sdfWrapper = new ThreadLocal() { - @Override
- protected SimpleDateFormat initialValue() {
- return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
- }
-
- };
-
- enum Label {
- INFO("INFO"),
- ERR("ERROR");
- String name;
-
- Label(String name) {
- this.name = name;
- }
-
- public String getName() {
- return name;
- }
- }
-
- // public static void info(String message) {
- // printf(Label.INFO, "%s", message);
- // }
-
- public static void info(String format, Object... args) {
- printf(Label.INFO, format, args);
- }
-
- public static void info(boolean message) {
- info("%s", message);
- }
-
- public static void info(int message) {
- info("%d", message);
- }
-
- public static void error(String message, Object... args) {
- printf(Label.ERR, message, args);
- }
-
- public static void printf(Label label, String format, Object... args) {
- SimpleDateFormat sdf = sdfWrapper.get();
- @SuppressWarnings("resource")
- final PrintStream ps = label == Label.INFO ? System.out : System.err;
- ps.printf('[' + sdf.format(new Date()) + "][" + label.getName()
- + "]["
- + Thread.currentThread().getName() + "]:" + format + " %n", args);
- }
- }
- import sun.misc.Unsafe;
-
- import java.io.*;
- import java.lang.reflect.Field;
- import java.math.BigInteger;
- import java.security.DigestInputStream;
- import java.security.MessageDigest;
- import java.security.NoSuchAlgorithmException;
- import java.util.Random;
- import java.util.logging.Level;
- import java.util.logging.Logger;
-
- public final class Tools {
- private static final Random rnd = new Random();
- private static final Logger LOGGER = Logger.getAnonymousLogger();
-
- public static void startAndWaitTerminated(Thread... threads)
- throws InterruptedException {
- if (null == threads) {
- throw new IllegalArgumentException("threads is null!");
- }
- for (Thread t : threads) {
- t.start();
- }
- for (Thread t : threads) {
- t.join();
- }
- }
-
- public static void startThread(Thread... threads) {
- if (null == threads) {
- throw new IllegalArgumentException("threads is null!");
- }
- for (Thread t : threads) {
- t.start();
- }
- }
-
- public static void startAndWaitTerminated(Iterable
threads) - throws InterruptedException {
- if (null == threads) {
- throw new IllegalArgumentException("threads is null!");
- }
- for (Thread t : threads) {
- t.start();
- }
- for (Thread t : threads) {
- t.join();
- }
- }
-
- public static void randomPause(int maxPauseTime) {
- int sleepTime = rnd.nextInt(maxPauseTime);
- try {
- Thread.sleep(sleepTime);
- } catch (InterruptedException e) {
- Thread.currentThread().interrupt();
- }
- }
-
- public static void randomPause(int maxPauseTime, int minPauseTime) {
- int sleepTime = maxPauseTime == minPauseTime ? minPauseTime : rnd
- .nextInt(maxPauseTime - minPauseTime) + minPauseTime;
- try {
- Thread.sleep(sleepTime);
- } catch (InterruptedException e) {
- Thread.currentThread().interrupt();
- }
- }
-
- public static Unsafe getUnsafe() {
- try {
- Field f = Unsafe.class.getDeclaredField("theUnsafe");
- ((Field) f).setAccessible(true);
- return (Unsafe) f.get(null);
- } catch (Exception e) {
- e.printStackTrace();
- }
- return null;
- }
-
- public static void silentClose(Closeable... closeable) {
- if (null == closeable) {
- return;
- }
- for (Closeable c : closeable) {
- if (null == c) {
- continue;
- }
- try {
- c.close();
- } catch (Exception ignored) {
- }
- }
- }
-
- public static void split(String str, String[] result, char delimeter) {
- int partsCount = result.length;
- int posOfDelimeter;
- int fromIndex = 0;
- String recordField;
- int i = 0;
- while (i < partsCount) {
- posOfDelimeter = str.indexOf(delimeter, fromIndex);
- if (-1 == posOfDelimeter) {
- recordField = str.substring(fromIndex);
- result[i] = recordField;
- break;
- }
- recordField = str.substring(fromIndex, posOfDelimeter);
- result[i] = recordField;
- i++;
- fromIndex = posOfDelimeter + 1;
- }
- }
-
- public static void log(String message) {
- LOGGER.log(Level.INFO, message);
- }
-
- public static String md5sum(final InputStream in) throws NoSuchAlgorithmException, IOException {
- MessageDigest md = MessageDigest.getInstance("MD5");
- byte[] buf = new byte[1024];
- try (DigestInputStream dis = new DigestInputStream(in, md)) {
- while (-1 != dis.read(buf))
- ;
- }
- byte[] digest = md.digest();
- BigInteger bigInt = new BigInteger(1, digest);
- String checkSum = bigInt.toString(16);
-
- while (checkSum.length() < 32) {
- checkSum = "0" + checkSum;
- }
- return checkSum;
- }
-
- public static String md5sum(final File file) throws NoSuchAlgorithmException, IOException {
- return md5sum(new BufferedInputStream(new FileInputStream(file)));
- }
-
- public static String md5sum(String str) throws NoSuchAlgorithmException, IOException {
- ByteArrayInputStream in = new ByteArrayInputStream(str.getBytes("UTF-8"));
- return md5sum(in);
- }
-
- public static void delayedAction(String prompt, Runnable action, int delay/* seconds */) {
- Debug.info("%s in %d seconds.", prompt, delay);
- try {
- Thread.sleep(delay * 1000);
- } catch (InterruptedException ignored) {
- }
- action.run();
- }
-
- public static Object newInstanceOf(String className) throws InstantiationException,
- IllegalAccessException, ClassNotFoundException {
- return Class.forName(className).newInstance();
- }
-
- }
《Java多线程编程实战指南-核心篇》