定時任務
- Rx
public class RxUtils {
static public Observable<Integer> countDown(int time) {
if (time < 0) time = 0;
final int countTime = time;
return Observable.interval(0, 1, TimeUnit.SECONDS)
.map(new Func1<Long, Integer>() {
@Override
public Integer call(Long increaseTime) {
return countTime - increaseTime.intValue();
}
})
.take(countTime + 1);
//
// Observable.timer(time,TimeUnit.SECONDS).filter(new Func1<Long, Boolean>() {
// @Override
// public Boolean call(Long aLong) {
// return null;
// }
// })
}
}
Timer
Timer timer = new Timer(); TimerTask timerTask = new TimerTask() { @Override public void run() { LogUtil.v("java", "任務開始"); } }; timer.schedule(timerTask, 1000); timer.schedule(timerTask, 1000); ps:timer.cancel;
Handler
Handler handler = new Handler(); Runnable runnable = new Runnable() { @Override public void run() { LogUtil.v("java", "定時任務開啓"); } }; handler.postDelayed(runnable, 1000); //handler.removeCallbacksAndMessages(null);
AlarmManager
am = (AlarmManager) this.getSystemService(ALARM_SERVICE); Intent i = new Intent(this, UpdateReceiver.class); PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, i, 0); //am.set(AlarmManager.RTC, System.currentTimeMillis() + 1000, pendingIntent); am.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime(), 1000, pendingIntent);
鎖機制
- 概念
- 原子性:只有一個線程能夠執行這個代碼
- 可見性: 保證前後修改的資源一致
分類
- synchronized
ReentrantLock:可重入的意義在於持有鎖的線程可以繼續持有,並且要釋放對等的次數後才真正釋放該鎖
class Outputter1 {
private Lock lock = new ReentrantLock();// 鎖對象public void output(String name) { lock.lock(); // 得到鎖 try { //do something } finally { lock.unlock();// 釋放鎖 } }
}
ReadWriteLock:可以同時讀取,限制寫入
class Data { private int data;// 共享數據 private ReadWriteLock rwl = new ReentrantReadWriteLock(); public void set(int data) { rwl.writeLock().lock();// 取到寫鎖 try { System.out.println(Thread.currentThread().getName() + "準備寫入數據"); try { Thread.sleep(20); } catch (InterruptedException e) { e.printStackTrace(); } this.data = data; System.out.println(Thread.currentThread().getName() + "寫入" + this.data); } finally { rwl.writeLock().unlock();// 釋放寫鎖 } } public void get() { rwl.readLock().lock();// 取到讀鎖 try { System.out.println(Thread.currentThread().getName() + "準備讀取數據"); try { Thread.sleep(20); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "讀取" + this.data); } finally { rwl.readLock().unlock();// 釋放讀鎖 } } }
和Condition的結合
class BoundedBuffer { final Lock lock = new ReentrantLock();//鎖對象 final Condition notFull = lock.newCondition();//寫線程條件 final Condition notEmpty = lock.newCondition();//讀線程條件 final Object[] items = new Object[100];//緩存隊列 int putptr/*寫索引*/, takeptr/*讀索引*/, count/*隊列中存在的數據個數*/; public void put(Object x) throws InterruptedException { lock.lock(); try { while (count == items.length)//如果隊列滿了 notFull.await();//阻塞寫線程 items[putptr] = x;//賦值 if (++putptr == items.length) putptr = 0;//如果寫索引寫到隊列的最後一個位置了,那麼置爲0 ++count;//個數++ notEmpty.signal();//喚醒讀線程 } finally { lock.unlock(); } } public Object take() throws InterruptedException { lock.lock(); try { while (count == 0)//如果隊列爲空 notEmpty.await();//阻塞讀線程 Object x = items[takeptr];//取值 if (++takeptr == items.length) takeptr = 0;//如果讀索引讀到隊列的最後一個位置了,那麼置爲0 --count;//個數-- notFull.signal();//喚醒寫線程 return x; } finally { lock.unlock(); } } }
多線程總結
管理類
基本
ExecutorService e = Executors.newCachedThreadPool(); ExecutorService e = Executors.newSingleThreadExecutor(); ExecutorService e = Executors.newFixedThreadPool(3); // 第一種是可變大小線程池,按照任務數來分配線程, // 第二種是單線程池,相當於FixedThreadPool(1) // 第三種是固定大小線程池。 // 然後運行 e.execute(new MyRunnableImpl());
定時任務線程
ScheduledExecutorService threadPools = Executors.newScheduledThreadPool(2); for(int i = 0; i < 2;i++){ threadPools.schedule(new Runnable() { @Override public void run() { System.out.println(Thread.currentThread().getName() + "定時器執行"); } }, 2, TimeUnit.SECONDS); } threadPools.shutdown(); //scheduleAtFixedRate 這個方法是不管你有沒有執行完,反正我每隔4秒來執行一次,以相同的頻率來執行 //scheduleWithFixedDelay 這個是等你方法執行完後,我再隔4秒來執行,也就是相對延遲後,以固定的頻率去執行
Semaphore就是一個信號量,它的作用是限制某段代碼塊的併發數
FutureTask類實現了RunnableFuture接口,我們看一下RunnableFuture接口的實現,RunnableFuture繼承了Runnable接口和Future接口,而FutureTask實現RunnableFuture接口。所以它既可以作爲Runnable被線程執行,又可以作爲Future得到Callable的返回值。
public class Test { public static void main(String[] args) { //第一種方式 ExecutorService executor = Executors.newCachedThreadPool(); Task task = new Task(); FutureTask<Integer> futureTask = new FutureTask<Integer>(task); executor.submit(futureTask); executor.shutdown(); //第二種方式,注意這種方式和第一種方式效果是類似的,只不過一個使用的是ExecutorService,一個使用的是Thread /*Task task = new Task(); FutureTask<Integer> futureTask = new FutureTask<Integer>(task); Thread thread = new Thread(futureTask); thread.start();*/ try { Thread.sleep(1000); } catch (InterruptedException e1) { e1.printStackTrace(); } System.out.println("主線程在執行任務"); try { System.out.println("task運行結果"+futureTask.get()); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } System.out.println("所有任務執行完畢"); } } class Task implements Callable<Integer>{ @Override public Integer call() throws Exception { System.out.println("子線程在進行計算"); Thread.sleep(3000); int sum = 0; for(int i=0;i<100;i++) sum += i; return sum; } }
參考
- http://blog.csdn.net/dxpqxb/article/details/8659292
- http://blog.csdn.net/vking_wang/article/details/9952063
- http://www.jianshu.com/p/40d4c7aebd66 多線程
- http://mybar.iteye.com/blog/1829883 線程池
- http://www.cnblogs.com/dolphin0520/p/3949310.html Future
- http://blog.csdn.net/yaojiank/article/details/8888186