Java并发编程实例--9.使用本地线程变量

并发程序一个重要方面就是共享数据。

这一点在继承了Thread类或实现了Runnable接口的对象中有着特殊的重要性。

如果你创建了一个实现了Runnable接口的类对象并且用这个对象开启了N个线程对象,那么所有这些线程对象共享同样的属性。

这意味着,如果你再某一线程中修改了属性值,所有其他线程将都能看到并受影响。


有时候,你可能对每个线程拥有自己私有的属性感兴趣。这也正是Java并发API提供的一项机制,

即:thread-local variables 本地线程变量。



本例中,我们会开发一个共享变量程序和一个本地线程变量程序作为对比。


UnsafeTask.java

package com.dylan.thread.ch1.c09.task;

import java.util.Date;
import java.util.concurrent.TimeUnit;

/**
 * Class that shows the problem generate when some Thread objects
 * share a data structure
 *
 */
public class UnsafeTask implements Runnable{

	/**
	 * Date shared by all threads
	 */
	private Date startDate;
	
	/**
	 * Main method of the class. Saves the start date and writes
	 * it to the console when it starts and when it ends
	 */
	@Override
	public void run() {
		startDate=new Date();
		System.out.printf("Starting Thread: %s : %s\n",Thread.currentThread().getId(),startDate);
		try {
			TimeUnit.SECONDS.sleep((int)Math.rint(Math.random()*10));
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.printf("Thread Finished: %s : %s\n",Thread.currentThread().getId(),startDate);
	}

}

Main.java
 
 
package com.dylan.thread.ch1.c09.core;

import com.dylan.thread.ch1.c09.task.UnsafeTask;

import java.util.concurrent.TimeUnit;

/**
 * Main class of the UnsafeTask. Creates a Runnable task and
 * three Thread objects that run it.
 *
 */
public class Main {

   /**
    * Main method of the UnsafeTaks. Creates a Runnable task and
    * three Thread objects that run it.
    * @param args
    */
   public static void main(String[] args) {
      // Creates the unsafe task
      UnsafeTask task=new UnsafeTask();
      
      // Throw three Thread objects
      for (int i=0; i<3; i++){
         Thread thread=new Thread(task);
         thread.start();
         try {
            TimeUnit.SECONDS.sleep(2);
         } catch (InterruptedException e) {
            e.printStackTrace();
         }
      }
   }
}

运行输出:

Starting Thread: 10 : Mon Apr 30 20:15:01 CST 2018
Starting Thread: 11 : Mon Apr 30 20:15:03 CST 2018
Starting Thread: 12 : Mon Apr 30 20:15:05 CST 2018
Thread Finished: 10 : Mon Apr 30 20:15:05 CST 2018
Thread Finished: 11 : Mon Apr 30 20:15:05 CST 2018

Thread Finished: 12 : Mon Apr 30 20:15:05 CST 2018


可以看到线程结束时间都和最后一个执行结束的线程12的时间一致,说明3个线程的时间变量是共享的。


SafeTask.java

package com.dylan.thread.ch1.c09.task;

import java.util.Date;
import java.util.concurrent.TimeUnit;

/**
 * Class that shows the usage of ThreadLocal variables to share
 * data between Thread objects
 *
 */
public class SafeTask implements Runnable {

	/**
	 * ThreadLocal shared between the Thread objects
	 */
	private static ThreadLocal<Date> startDate= new ThreadLocal<Date>() {
		protected Date initialValue(){
			return new Date();
		}
	};
	

	/**
	 * Main method of the class
	 */
	@Override
	public void run() {
		// Writes the start date
		System.out.printf("Starting Thread: %s : %s\n",Thread.currentThread().getId(),startDate.get());
		try {
			TimeUnit.SECONDS.sleep((int)Math.rint(Math.random()*10));
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		// Writes the start date
		System.out.printf("Thread Finished: %s : %s\n",Thread.currentThread().getId(),startDate.get());
	}

}

SafeMain.java

package com.dylan.thread.ch1.c09.core;

import com.dylan.thread.ch1.c09.task.SafeTask;

import java.util.concurrent.TimeUnit;


/**
 * Main class of the example.
 *
 */
public class SafeMain {

	/**
	 * Main method of the example
	 * @param args
	 */
	public static void main(String[] args) {
		// Creates a task
		SafeTask task=new SafeTask();
		
		// Creates and start three Thread objects for that Task
		for (int i=0; i<3; i++){
			Thread thread=new Thread(task);
			try {
				TimeUnit.SECONDS.sleep(2);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			thread.start();
		}

	}

}


运行输出:

Starting Thread: 10 : Mon Apr 30 20:12:45 CST 2018
Starting Thread: 11 : Mon Apr 30 20:12:47 CST 2018
Thread Finished: 10 : Mon Apr 30 20:12:45 CST 2018
Starting Thread: 12 : Mon Apr 30 20:12:49 CST 2018
Thread Finished: 12 : Mon Apr 30 20:12:49 CST 2018
Thread Finished: 11 : Mon Apr 30 20:12:47 CST 2018


可以看到3个线程的时间都不一样,说明没有共享。







猜你喜欢

转载自blog.csdn.net/indexman/article/details/80151611