您的位置:首页 > 编程语言 > Java开发

Java多线程,线程同步synchronized,线程死锁【线程池常规用法】多线程并发处理

2016-07-14 09:01 976 查看
工作内容:

1.线程同步:synchronized (锁类)
2.线程死锁(Thread.join(),Synchronized)
3.生产者与消费者模式
4.线程练习
5.线程池
6.多线程并发ThreadLocal与Synchronized
线程同步:

Synchronized(Object){
代码块 }

Public static synchronized void method(){
代码块 }

尽量用在最细致的地方(精确位置)

线程死锁:发生在请求同步方法,同步方法请求同一个对象时



实例1:线程死锁的实现1(Synchronized)

private Object obj1 = new Object(),obj2 = new Object();
//..........同时调用下列2个方法
private void startlock2() {
new Thread(){
@Override
public void run() {
synchronized (obj1){
try {
Thread.sleep(1000);//睡眠1秒
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.e("-------","已锁定obj1-----正在锁定obj2....");
synchronized(obj2){
Log.e("-------","已锁定obj1并且锁定了obj2");
}
}
}
}.start();
}

private void startlock1() {
new Thread(){
@Override
public void run() {
synchronized (obj2){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.e("-------","已锁定obj2-----正在锁定obj1...");
synchronized(obj1){
Log.e("-------","已锁定obj2并且锁定了obj1");
}
}
}
}.start();
}
得到结果:
已锁定obj2-----正在锁定obj1...

已锁定obj1-----正在锁定obj2...

说明:两个方法锁定了第一个对象后都没有成功锁定另外一个对象造成死锁

实例1:线程死锁的实现2(Thread.join())

private void startlock2() {
thread = new Thread() {
@Override
public void run() {
Log.e("-------", "执行thread");
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.e("-------", "执行thread完成");
}
};
new Thread() {
@Override
public void run() {
Log.e("-------", "执行join");
try {
thread.start();
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.e("-------", "执行完毕");
}
}.start();
}
运行结果:【join的线程先执行完成才会继续执行原线程】

执行join

执行thread

执行thread完成

执行完毕

实例2:(通过Runnable实现数据共享)

//摇出三个36以内的随机号码

import java.util.ArrayList;

public class Test4 {
public static void main(String[] args) {
ProduceNum num = new ProduceNum();
new Thread(num).start();
new Thread(num).start();
new Thread(num).start();
//打印语句可能先于线程的执行,先暂停主线程
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(ProduceNum.list);
}
}

class ProduceNumimplements Runnable {
static ArrayList<Integer> list = new ArrayList<Integer>();

@Override
public void run() {
GetRondom.getNum();
}
}

//产生随机数的类0-37前闭后开
class GetRondom {
public static void getNum() {
int x = (int) (Math.random() * 37);
ProduceNum.list.add(x);
}
}

5.线程池:

Java通过Executors提供四种线程池,分别为:

1.newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。

public static void main(String[] args) {
ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
for (int i = 0; i < 10; i++) {
final int index = i;
try {
Thread.sleep(index * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
cachedThreadPool.execute(new Runnable() {
public void run() {
System.out.println(index);
}
});
}
}


2.newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。

ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);
fixedThreadPool.execute(new Runnable() {
public void run() {
try {
System.out.println(index);
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});


3.newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行。

ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);
scheduledThreadPool.schedule(new Runnable() {
public void run() {
System.out.println("delay 3 seconds");
}
}, 3, TimeUnit.SECONDS);//延迟3秒执行
}


定期执行

ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);
scheduledThreadPool.scheduleAtFixedRate(new Runnable() {
public void run() {
System.out.println("delay 1 seconds, and excute every 3 seconds");
}
}, 1, 3, TimeUnit.SECONDS); //延迟1秒执行,每3秒执行一次
}


4.newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO,
LIFO, 优先级)执行

ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
singleThreadExecutor.execute(new Runnable() {
public void run() {
try {
System.out.println(index);
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});

2种执行方式:

single.execute(new Runnable() {//同步
@Override
public void run() {

}
});
single.submit(new Runnable
c277
() {//提交
@Override
public void run() {

}
});
6.多线程并发问题
对ThreadLocal的理解,【可以点进去看看】

ThreadLocal:“以空间换时间”的方式处理多线程并发(操作同一个对象)问题——为每个线程创建一个对应线程的对象的副本

Synchronized:"以时间换空间"的方式处理多线程并发(操作同一个对象)问题——同一时刻只准一个线程访问该对象

最常见的ThreadLocal使用场景为 用来解决 数据库连接、Session管理等。

实例:数据库链接

private static ThreadLocal<Connection> connectionHolder = new ThreadLocal<Connection>() {
public Connection initialValue() {
return DriverManager.getConnection(DB_URL);
}
};

public static Connection getConnection() {
return connectionHolder.get();
}

实例:会话控制

private static final ThreadLocal threadSession = new ThreadLocal();

public static Session getSession() throws InfrastructureException {
Session s = (Session) threadSession.get();
try {
if (s == null) {
s = getSessionFactory().openSession();
threadSession.set(s);
}
} catch (HibernateException ex) {
throw new InfrastructureException(ex);
}
return s;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: