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

Java死锁和线程范围内共享数据

2018-04-10 15:01 399 查看
一般来说:出现死锁问题要满足以下条件

互斥条件:一个资源每次只能被一个线程访问

请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放

不剥夺条件:进程已获得的资源,在未使用完之前,不能剥夺。

循环等待条件:若干进程之间形成一种头尾相接的循环等待状态

只要破坏其中任意一个,死锁的问题就能被解决

二:线程范围内共享数据

所谓线程范围内共享数据,即对于相同的程序代码,多个模块在统一线程运行中要共享一份数据,Api为我们提供了一个线程范围内共享数据的类ThreadLocal

使用map实现线程范围内数据的共享

原理:将线程对象作为map的键存入,这样就保证了map对象的唯一,也就保证了数据的唯一。

package com.java.day8;

import java.util.HashMap;
import java.util.Map;
import java.util.Random;

/**
* Created by wangkaishuang on 18-4-10
*/
public class ThreadScopeShareData {
private static int data = 0;
private static Map<Thread,Integer> threadData = new HashMap<>();

public static void main(String[] args) {
for (int i = 0; i < 2; i++) {
new Thread(new Runnable() {
@Override
public void run() {
int data = new Random().nextInt();
threadData.put(Thread.currentThread(), data);
System.out.println(Thread.currentThread() + "has input data" + data);
new A().get();
new B().get();
}
}).start();
}
}
static class A {
public void get() {
int data = threadData.get(Thread.currentThread());
System.out.println("A from " + Thread.currentThread().getName()
+ " get data :" + data);
}
}

static class B{
public void get(){
int data = threadData.get(Thread.currentThread());
System.out.println("B from " + Thread.currentThread().getName()
+ " get data :" + data);
}
}
}


ThreadLocal类

1)该示例包含了对基本数据类型的共享和对象数据类型的共享

2)定义一个全局共享的ThreadLocal变量,然后启动多个线程向该ThreadLocal变量随机存储一个值,接着,各个线程调用其他类的方法读取ThreadLocal变量的值,就可以看到多个类在同一线程共享同一份数据。

3)每次存储数据时,用的都是同一个ThreadLocal变量,只是重新赋值而已

package com.java.day8;

import java.util.HashMap;
import java.util.Map;
import java.util.Random;

public class ThreadLocalDemo {

private static ThreadLocal<Integer> x = new ThreadLocal<Integer>();
//创建一个存储封装类对象的ThreadLocal
private static ThreadLocal<MyThreadScopeData> myThreadScopeData = new  ThreadLocal<MyThreadScopeData>();
private static int data = 0;

public static void main(String[] args){

//产生两个线程
for(int i=0;i<2;i++){
new Thread(new Runnable(){

@Override
public void run() {
//共享单一的数据
int data = new Random().nextInt();
System.out.println(Thread.currentThread().getName()+"has put data : "+data);
x.set(data);

//共享多个数据
//将数据封装在myData对象中,并将myData作为myThreadScopeData的键
MyThreadScopeData myData = new MyThreadScopeData();
myData.setName("name "+data);
myData.setAge(data);
myThreadScopeData.set(myData);

new A().get();
new B().get();
}
}).start();
}
}

static class A{
public void get(){
int data = x.get();
System.out.println("A from "+Thread.currentThread().getName()+" get data :"+data);

//从myData中取出数据,并获取当前线程名,数据
MyThreadScopeData myData = myThreadScopeData.get();
System.out.println("A from "+Thread.currentThread().getName()+" getMyData: " +
myData.getName() + "," +myData.getAge());
}
}

static class B{
public void get(){
int data = x.get();
System.out.println("B from "+Thread.currentThread().getName()+" get data :"+data);
MyThreadScopeData myData = myThreadScopeData.get();
System.out.println("B from "+Thread.currentThread().getName()+" getMyData: " +
myData.getName() + "," +myData.getAge());
}
}
}

//封装数据的类
class MyThreadScopeData{

private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐