/* * JEF - Copyright 2009-2010 Jiyi (mr.jiyi@gmail.com) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package jef.tools; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import jef.common.log.LogUtil; import jef.tools.reflect.UnsafeUtils; /** * 用于并发编程得的若干简单小工具 * * @author Jiyi * */ public abstract class ThreadUtils { public static final int WAIT_INTERRUPTED = 0; public static final int WAIT_TIMEOUT = -1; public static final int WAIT_NOTIFIED = 1; /** * 让出指定对象的锁,并且挂起当前线程。只有当—— <li>1. 有别的线程notify了对象,并且锁没有被其他线程占用。</li> <li>2 * 有别的线程interrupt了当前线程。</li> 此方法才会返回。 * @param obj 锁所在的对象 * @return 等待正常结束返回true,异常结束返回false */ public static final boolean doWait(Object obj) { synchronized (obj) { try { obj.wait(); return true; } catch (InterruptedException e) { LogUtil.exception(e); return false; } } } /** * 等待CountDownLatch数据清零 * @param cl * @return */ public static final boolean doAwait(CountDownLatch cl) { try { cl.await(); return true; } catch (InterruptedException e) { return false; } } /** * 调用对象的wait方法,并设置超时时间 * @param obj 锁所在的对象 * @param timeout 超时时间,单位毫秒 * @return 超时返回 {@link #WAIT_TIMEOUT}; * 正常唤醒{@link #WAIT_NOTIFIED}; * 异常打断{@link #WAIT_INTERRUPTED } */ public static final int doWait(Object obj, long timeout) { synchronized (obj) { try { long expectTimeout = System.currentTimeMillis() + timeout; obj.wait(timeout); return System.currentTimeMillis() >= expectTimeout ? WAIT_TIMEOUT : WAIT_NOTIFIED; } catch (InterruptedException e) { return WAIT_INTERRUPTED; } } } /** * 在新的线程中运行指定的任务 * @param runnable Runnable * @return */ public static final Thread doTask(Runnable runnable) { Thread t = new Thread(runnable); t.setDaemon(true); t.start(); return t; } /** * 唤醒一个在等待obj锁的线程 */ public static final void doNotify(Object obj) { synchronized (obj) { obj.notify(); } } /** * 唤醒所有在等待obj的锁的线程。 * * @param obj */ public static final void doNotifyAll(Object obj) { synchronized (obj) { obj.notifyAll(); } } /** * 当前线程等待若干毫秒 * * @param l * 毫秒数 * @return 如果是正常休眠后返回的true,因为InterruptedException被打断的返回false */ public static final boolean doSleep(long l) { if (l <= 0) return true; try { Thread.sleep(l); return true; } catch (InterruptedException e) { LogUtil.exception(e); return false; } } /** * 判断当前该对象是否已锁。<br> 注意在并发场景下,这一操作只能反映瞬时的状态,仅用于检测,并不能认为本次检测该锁空闲,紧接着的代码就能得到锁。 * * @param obj * @return */ @SuppressWarnings("restriction") public static boolean isLocked(Object obj) { sun.misc.Unsafe unsafe = UnsafeUtils.getUnsafe(); if (unsafe.tryMonitorEnter(obj)) { unsafe.monitorExit(obj); return false; } return true; } /** * 在执行一个同步方法前,可以手工得到锁。<p> * * 这个方法可以让你在进入同步方法或同步块之前多一个选择的机会。因为这个方法不会阻塞,如果锁无法得到,会返回false。 * 如果返回true,证明你可以无阻塞的进入后面的同步方法或同步块。<p> * * 要注意,用这个方法得到的锁不会自动释放(比如在同步块执行完毕后不会释放),必须通过调用unlock(Object)方法才能释放。 需小心使用。<p> * * @param obj * @return 如果锁得到了,返回true,如果锁没有得到到返回false */ @SuppressWarnings("restriction") public static boolean tryLock(Object obj) { sun.misc.Unsafe unsafe = UnsafeUtils.getUnsafe(); return unsafe.tryMonitorEnter(obj); } /** * 释放因为lock/tryLock方法得到的锁 * * @param obj */ @SuppressWarnings("restriction") public static void unlock(Object obj) { sun.misc.Unsafe unsafe = UnsafeUtils.getUnsafe(); unsafe.monitorExit(obj); } /** * 对CountDownLatch进行等待。如果正常退出返回true,异常退出返回false * @param cl CountDownLatch * @return 果正常退出返回true,异常退出返回false */ public static boolean await(CountDownLatch cl) { try { cl.await(); return true; } catch (InterruptedException e) { return false; } } /** * 对CountDownLatch进行等待。如果正常退出返回true,超时或者异常退出返回false * @param cl CountDownLatch * @param millseconds 超时时间,单位毫秒 * @return 如果正常退出true。 如果超时或异常退出false */ public static boolean await(CountDownLatch cl,long millseconds) { try { return cl.await(millseconds, TimeUnit.MILLISECONDS); } catch (InterruptedException e) { return false; } } }