最近一直做推送平台上的修改,涉及到一些多线程的东西,所以就看了一些资料和代码,并稍微做了一点笔记。
— 技术点 —
1.synchronized
a. 方法级别synchronized ,排队调用方法
b. A.class 中两个方法 ,一个同步了,另一个没有 ,多个线程进行调用时,未同步的不受影响
c. synchronized 锁重入 :当一个线程得到一个对象锁之后,再次请求此对象锁是是可以再次得到该对象的锁的,这也证明在一个synchronized方法/块的内部调用本类的其他这也证明在一个synchronized方法/块时,是永远可以得到锁的。
d. synchronized代码块 :(demo)
public class Task {
public void otherMethod() {
System.out.println("------------------------run--otherMethod");
}
public void doLongTimeTask() {
synchronized (this) {
for (int i = 0; i < 1000; i++) {
System.out.println("synchronized threadName="
+ Thread.currentThread().getName() + " i=" + (i + 1));
}
}
}
}
public class MyThread1 extends Thread {
private Task task;
public MyThread1(Task task) {
super();
this.task = task;
}
@Override
public void run() {
super.run();
task.doLongTimeTask();
}
}
public class MyThread2 extends Thread {
private Task task;
public MyThread2(Task task) {
super();
this.task = task;
}
@Override
public void run() {
super.run();
task.otherMethod();
}
}
public static void main(String[] args) throws InterruptedException {
Task task = new Task();
MyThread1 thread1 = new MyThread1(task);
thread1.start();
Thread.sleep(100);
MyThread2 thread2 = new MyThread2(task);
thread2.start();
}
e. synchronized锁的对象一定要是单例的
f. 3个结论
当多个线程同时执行synchronized(x){}同步代码块时呈同步效果
当其他线程执行x对象中synchronized同步方法时呈同步效果
当其他线程执行x对象方法里面synchronized(this)代码块时也呈现同步结果
g. 关键字synchronized还可以应用在static静态方法上,如果这样写,就是对当前的.java文件对应的class类进行持锁。加在非静态方法上是给对象上锁。class锁可以对类的所有对象锁实例起作用。
2.线程间的通信
a. notify();的使用:必须执行完notify()方法所在同步synchronized代码块后才释放锁 (demo代码)
public void testMethod(Object lock) {
try {
synchronized (lock) {
System.out.println("begin wait() ThreadName="
+ Thread.currentThread().getName());
lock.wait();
System.out.println(" end wait() ThreadName="
+ Thread.currentThread().getName());
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void synNotifyMethod(Object lock) {
try {
synchronized (lock) {
System.out.println("begin notify() ThreadName="
+ Thread.currentThread().getName() + " time="
+ System.currentTimeMillis());
lock.notify();
Thread.sleep(5000);
System.out.println(" end notify() ThreadName="
+ Thread.currentThread().getName() + " time="
+ System.currentTimeMillis());
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
b. notify();多个线程的时候,只是随机的通知一个线程,notifyAll();可以唤醒全部。
c. 一生产一消费:操作值 (操作栈)
3.Lock类
a. lock的lock()和unlock();
b. Condition类实现等待和通知:在一个Lock对象里可以创建多个Condition(对象监视器)实例,线程对象;可以注册在指定的Condition中,从而可以有选择的进行线程通知
c. 生产者/消费者模式:一对一交替打印 (demo)
public class C {
private String lock;
public C(String lock) {
super();
this.lock = lock;
}
public void getValue() {
try {
synchronized (lock) {
if (ValueObject.value.equals("")) {
lock.wait();
}
System.out.println("get---" + ValueObject.value);
ValueObject.value = "";
lock.notify();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class P {
private String lock;
public P(String lock) {
super();
this.lock = lock;
}
public void setValue() {
try {
synchronized (lock) {
if (!ValueObject.value.equals("")) {
lock.wait();
}
String value = System.currentTimeMillis() + "_"
+ System.nanoTime();
System.out.println("set----" + value);
ValueObject.value = value;
lock.notify();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class ValueObject {
public static String value = "";
}
public class ThreadC extends Thread {
private C r;
public ThreadC(C r) {
super();
this.r = r;
}
@Override
public void run() {
while (true) {
r.getValue();
}
}
}
public class ThreadP extends Thread {
private P p;
public ThreadP(P p) {
super();
this.p = p;
}
@Override
public void run() {
while (true) {
p.setValue();
}
}
}
public static void main(String[] args) {
String lock = new String("");
P p = new P(lock);
C r = new C(lock);
ThreadP pThread = new ThreadP(p);
ThreadC rThread = new ThreadC(r);
pThread.start();
rThread.start();
}
d. 公平锁与非公平锁:公平锁先进先出 ,非公平锁随机的
4.Timer
a.定时器timer(是一个用户线程,默认的情况下,可以设置为守护线程)
b.schedule(TimerTask task,long delay,long period);
c.scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit);schedule():没有延时,下一次执行时间从上一次任务的开始时间计算;scheduleAtFixedRate():没有延时,下一次执行时间从上一次任务的结束时间计算;延时的情况都一样:都是从结束时间开始计算
5.延迟加载/“懒汉模式”的解决方案
延迟加载就是在调用get()方法时实例才被创建,常见的实现方式就是在get方法中进行new实例化。
a.demo代码
public class MyThread extends Thread {
@Override
public void run() {
System.out.println(MyObject.getInstance().hashCode());
}
}
public class Run {
public static void main(String[] args) {
MyThread t1 = new MyThread();
t1.start();
}
}
public class MyObject {
private static MyObject myObject;
private MyObject() {
}
public static MyObject getInstance() {
if (myObject != null) {
} else {
myObject = new MyObject();
}
return myObject;
}
}
— 项目中的代码的举例 —
1.定时器的使用
ThreadPoolHandle.installScheduledThreadPool().scheduleAtFixedRate(TaskHandleOne.tasks(null),1, 3, TimeUnit.SECONDS);
线程池处理,使用定时器:(Runnable,初始化延迟,每次延迟,时间格式)
ScheduledExecutorService 的api : http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ScheduledExecutorService.html
2.延迟加载/“懒汉模式” 及 synchronized关键字
public static MapCacheManager getInstance(){
synchronized (MapCacheManager.class) {
if(null == manager)
manager = new MapCacheManager();
return manager;
}
}
使用的时候:private CacheManager cacheManager = MapCacheManager.getInstance();
3.缓存的使用
private ConcurrentHashMap
获取 Cache实例
@Override
public Cache nativeCache(String cacheName,long expiredTime) throws CacheException {
synchronized (cacheMap){
if(!cacheMap.containsKey(cacheName)){
cacheMap.put(cacheName, new MapCache(cacheName));
logger.info("********nativeCache******: no containsKey");
}
logger.info("********nativeCache******: out");
MapCache mapCache = cacheMap.get(cacheName);
mapCache.setExpiredTime(expiredTime);
return mapCache;
}
}
取: Cache cache = cacheManager.nativeCache(FAILPUSHCONTENT);
存: cache.put(fpceList,FPCELISTKEY);
存和取的时候注意加锁:
synchronized(cacheManager){
Cache cache = cacheManager.nativeCache("failPushContent");
}
synchronized(){}注意是单例
4.管道队列的使用
public static Map
初始化管道:
depueMap.put(FOSS_DEPUE, new LinkedBlockingDeque<Maininformation>(1800));
depueMap.put(CONFIRM_DEPUE, new LinkedBlockingDeque<Maininformation>(1500));
depueMap.put(QUOTE_DEPUE, new LinkedBlockingDeque<Maininformation>(1500));
存数据:
depueMap.get(qequeType).put(obj);
取数据:
if(QueueHandle.depueMap.get(QueueHandle.QUOTE_DEPUE).peek() != null){ ThreadPoolHandle.installFixedThreadPoll().
execute(taskHandleParent.taskByOutSide(QueueHandle.depueMap.get(QueueHandle.QUOTE_DEPUE).poll()));
}
ThreadPoolHandle.installFixedThreadPoll()得到的数据是 ExecutorService fixedThreadPool
BlockingDeque 的api : http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/BlockingQueue.html