【Java多线程系列二】Thread类的方法
Thread实现Runnable接口并实现了大量实用的方法。
/* * 此方法释放CPU,但并不释放已获得的锁,其它就绪的线程将可能得到执行机会,它自己也有可能再次得到执行机会 */ public static native void yield(); /* * 此方法释放CPU,但并不释放已获得的锁,其它就绪的线程将得到执行机会,在休眠时间结束后,当前线程继续执行 */ public static native void sleep(long millis) throws InterruptedException; /* * 一旦调用后宿主线程将阻塞,待当前线程结束后继续 */ public final void join() throws InterruptedException; /* * 一旦调用后宿主线程将阻塞,待当前线程结束后继续 */ public final synchronized void join(long millis)throws InterruptedException; /* * 中断线程 */ public void interrupt(); /* * on=true表示线程标记为守护线程(例如GC线程),若正在运行的所有线程都是守护线程,JVM将退出 */ public final void setDaemon(boolean on);
Java代码:
import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicInteger; import org.junit.Assert; import org.junit.Test; /** * @Description: 测试Thread的方法 */ public class ThreadMethodsTest { static String SLEEP = "sleep"; static String YIELD = "yield"; static String JOIN = "join"; private Map<String, ThreadMethodEnum> map = new ConcurrentHashMap<>(); class ThreadSleep implements Runnable { private int millis; public ThreadSleep(int millis) { this.millis = millis; } @Override public void run() { System.out.println("Thread sleep run()..."); long threadId = Thread.currentThread().getId(); ThreadMethodEnum sleep = ThreadMethodEnum.SLEEP; sleep.init(threadId); try { Thread.sleep(millis); } catch (InterruptedException e) { e.printStackTrace(); } sleep.stop(); map.put(sleep.getMethod(), sleep); } } class ThreadYield implements Runnable { @Override public void run() { long threadId = Thread.currentThread().getId(); ThreadMethodEnum yield = ThreadMethodEnum.YIELD; yield.init(threadId); Thread.yield(); yield.stop(); map.put(yield.getMethod(), yield); } } class ThreadJoin implements Runnable { private Thread thread; private int millis = 0; public ThreadJoin(Thread thread) { this.thread = thread; } public ThreadJoin(Thread thread, int millis) { this.thread = thread; this.millis = millis; } @Override public void run() { try { System.out.println("Thread join run()..."); long threadId = Thread.currentThread().getId(); ThreadMethodEnum join = ThreadMethodEnum.JOIN; join.init(threadId); if (millis > 0) { this.thread.join(millis); } else { this.thread.join(); } join.stop(); map.put(join.getMethod(), join); } catch (InterruptedException e) { e.printStackTrace(); } } } final AtomicInteger interruptCount = new AtomicInteger(0); final int interruptIndex = 100; class ThreadInterrupt extends Thread { @Override public void run() { while (!isInterrupted()) { interruptCount.incrementAndGet(); if (interruptCount.intValue() == interruptIndex) { interrupt(); } } } } @Test public void testSleep() throws InterruptedException { int millis = 1000; Thread sleep = new Thread(new ThreadSleep(millis)); sleep.start(); sleep.join(); ThreadMethodEnum tme = map.get(SLEEP); // 预期sleep时间与millis相近 Assert.assertEquals(1, Math.round((tme.getStopTimeMillis() - tme.getStartTimeMillis()) * 1.0 / millis)); } @Test public void testYield() throws InterruptedException { Thread yield = new Thread(new ThreadYield()); yield.start(); yield.join(); ThreadMethodEnum tme = map.get(YIELD); // 预期yield消耗时间几乎为0 Assert.assertEquals(1, Math.round(tme.getStartTimeMillis() * 1.0 / tme.getStopTimeMillis())); } @Test public void testJoin() throws InterruptedException { System.out.println("testJoin() ---- start----"); int millis = 1000; Thread sleep = new Thread(new ThreadSleep(millis)); sleep.setName("Sleep Thread"); sleep.start(); Thread join = new Thread(new ThreadJoin(sleep)); join.setName("Join Thread"); join.start(); join.join(); ThreadMethodEnum tme = map.get(SLEEP); // 预期sleep时间与millis相近 Assert.assertEquals(1, Math.round((tme.getStopTimeMillis() - tme.getStartTimeMillis()) * 1.0 / millis)); tme = map.get(JOIN); // 预期join阻塞时间与millis相近 Assert.assertEquals(1, Math.round((tme.getStopTimeMillis() - tme.getStartTimeMillis()) * 1.0 / millis)); System.out.println("testJoin() ---- end----"); } @Test public void testJoinMillis() throws InterruptedException { System.out.println("testJoinMillis() ---- start----"); int millis = 500; Thread sleep = new Thread(new ThreadSleep(millis * 2)); sleep.setName("Sleep Thread"); sleep.start(); Thread join = new Thread(new ThreadJoin(sleep, millis)); join.setName("Join Thread"); join.start(); join.join(); ThreadMethodEnum tme = map.get(SLEEP); //预期sleep 不能在join阻塞结束前设置,固为null Assert.assertTrue(tme == null); tme = map.get(JOIN); //预期join阻塞时间与millis相近 Assert.assertEquals(1, Math.round((tme.getStopTimeMillis() - tme.getStartTimeMillis()) / millis)); System.out.println("testJoinMillis() ---- end----"); } @Test public void testInterrupt() throws InterruptedException { ThreadInterrupt interrupt = new ThreadInterrupt(); interrupt.start(); interrupt.join(); Assert.assertEquals(interruptIndex, interruptCount.intValue()); } } enum ThreadMethodEnum { SLEEP(ThreadMethodsTest.SLEEP) { @Override public void init(long threadId) { super.start(threadId); } }, YIELD(ThreadMethodsTest.YIELD) { @Override public void init(long threadId) { super.start(threadId); } }, JOIN(ThreadMethodsTest.JOIN) { @Override public void init(long threadId) { super.start(threadId); } }; private String method; private long threadId; private long startTimeMillis; private long stopTimeMillis = 0; private ThreadMethodEnum(String method) { this.method = method; } public void stop() { this.stopTimeMillis = System.currentTimeMillis(); } public String getMethod() { return method; } public long getThreadId() { return threadId; } public long getStartTimeMillis() { return startTimeMillis; } public long getStopTimeMillis() { return stopTimeMillis; } private void start(long threadId) { this.threadId = threadId; this.startTimeMillis = System.currentTimeMillis(); } public abstract void init(long threadId); }