java 多线程 解决资源冲突

来源:互联网 发布:c语言中&是什么意思 编辑:程序博客网 时间:2024/06/13 21:14

/** * 在其他对象上同步 *  * DualSync.f()(通过同步整个方法)在this同步,而g()有一个在syncObject上同步 * 的synchronized块。因此,这两个同步是互相独立的。 *  * @create @author Henry @date 2016-12-06  */class DualSynch {private Object syncObject = new Object();public synchronized void f() {for (int i = 0; i < 5; i++) {System.out.print("f()");Thread.yield();}}public void g() {synchronized (syncObject) {for (int i = 0; i < 5; i++) {System.out.print("g()");Thread.yield();}}}}/** * 通过main()中创建调用f()的Thread对这一点进行了演示,因为main()线程是被用来调用g()的。 * 从输出中可以看到,这两个方式在同时运行,因此任何方法都没有因为对另一个方法的 * 同步而被阻塞。 *  * @create @author Henry @date 2016-12-06 * */public class SyncObject {/** * 运行结果可能是: * g()f()g()f()g()f()g()f()g()f() * @param args */public static void main(String[] args) {final DualSynch ds = new DualSynch();new Thread() {public void run() {ds.f();};}.start();ds.g();}}
import java.util.Random;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.TimeUnit;/**线程本地存储  *  * 防止任务在共享资源上产生冲突的第二种是根除对变量的共享。线程本地存储是一种自动化机制, * 可以为使用相同变量的每个不同的线程都创建不同的存储。因此如果你有5个线程都要使用变量 x * 所表示的对象,那线程本地存储就会生成5个用于x的不同存储块。主要是,它们使得你可以将状态 * 与线程关联起来。 * 创建和管理线程本地存储可以由java.lang.ThreadLocal类实现,如下所示: *  *  * @create @author Henry @date 2016-12-06  * */class Accessor implements Runnable{private final int id;public Accessor(int idn){this.id=idn;}@Overridepublic void run() {while(!Thread.currentThread().isInterrupted()){ThreadLocalVariableHolder.increment();System.out.println(this);Thread.yield();}}@Overridepublic String toString() {return "#"+id+": "+ThreadLocalVariableHolder.get() ;}}/** *  * ThreadLocal对象通常当作静态域存储。在创建ThreadLocal时,你只能通过get()和set()方法 * 来访问该对象的内容,其中,get()方法将返回与线程相关联的对象的副本,而set()会将参数到插入 * 到为其线程存储的对象中,并返回存储中原有的对象。increment()和get()方法在 * ThreadLocalVariableHolder中演示了这一点。注意,increment()和get()方法都不是 * synchronized的,因为ThreadLocal保存不会出现竞争条件。 *  * 当运行这个程序时,你可以看到每个单独的线程都被分配了自己的存储,因为它们每个都需要跟踪 * 自己的计数器,即便只有一个ThreadLocalVariableHolder对象。 *  * @create @author Henry @date 2016-12-06  * */public class ThreadLocalVariableHolder {private static ThreadLocal<Integer> value=new ThreadLocal<Integer>(){private Random rand=new Random(47);protected synchronized Integer initialValue(){return rand.nextInt();}};public static void increment(){value.set(value.get()+1);}public static int get(){return value.get();}public static void main(String[] args) throws Exception {ExecutorService exec =Executors.newCachedThreadPool();for (int i = 0; i < 5; i++) exec.execute(new Accessor(i));TimeUnit.SECONDS.sleep(3);exec.shutdown();}}

附录:ThreadLocal在JDK 中的介绍,如下:

public class ThreadLocal<T>
extends Object

该类提供了线程局部 (thread-local) 变量。这些变量不同于它们的普通对应物,因为访问某个变量(通过其 getset 方法)的每个线程都有自己的局部变量,它独立于变量的初始化副本。ThreadLocal 实例通常是类中的 private static 字段,它们希望将状态与某一个线程(例如,用户 ID 或事务 ID)相关联。

例如,以下类生成对每个线程唯一的局部标识符。线程 ID 是在第一次调用 UniqueThreadIdGenerator.getCurrentThreadId() 时分配的,在后续调用中不会更改。

  import java.util.concurrent.atomic.AtomicInteger; public class UniqueThreadIdGenerator {     private static final AtomicInteger uniqueId = new AtomicInteger(0);     private static final ThreadLocal < Integer > uniqueNum =          new ThreadLocal < Integer > () {             @Override protected Integer initialValue() {                 return uniqueId.getAndIncrement();         }     };      public static int getCurrentThreadId() {         return uniqueId.get();     } } // UniqueThreadIdGenerator 

每个线程都保持对其线程局部变量副本的隐式引用,只要线程是活动的并且 ThreadLocal 实例是可访问的;在线程消失之后,其线程局部实例的所有副本都会被垃圾回收(除非存在对这些副本的其他引用)。




0 0
原创粉丝点击