一场雨

多线程部分小结

最近一直做推送平台上的修改,涉及到一些多线程的东西,所以就看了一些资料和代码,并稍微做了一点笔记。

— 技术点 —

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 cacheMap = new ConcurrentHashMap(0);

获取 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 = new HashMap>();

初始化管道:

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