当前所在位置:珠峰网资料 >> 计算机 >> 计算机等级考试 >> 正文
Java基础:关于线程安全
发布时间:2010/6/29 11:38:12 来源:城市学习网 编辑:ziteng
  线程安全的本质体现在两个方面,
  A变量安全:多线程同时运行一段代码
  B线程同步:一个线程还没执行完,另一个线程又进来接着执行。
  看个简单的例子。
  Java代码
  public class ThreadSafe implements java.lang.Runnable {
  int num = 1;
  public void run() {
  for (int i = 0; i < 3; i++) {
  num = num + 1;
  try {
  Thread.sleep(2000);
  } catch (InterruptedException e) {
  e.printStackTrace();
  }
  System.out.println("num is value +==="+Thread.currentThread().getName()+"---------" + num);
  }
  }
  }
  TestMan.java 写道
  package com.java.thread.test;
  public class TestMan {
  public static void main(String[] args) {
  Runnable safe=new ThreadSafe();
  Thread thread1=new Thread(safe,"thread1");
  Thread thread2=new Thread(safe,"thread2");
  thread1.start();
  thread2.start();
  }
  }
  运行结果
  num is value +===thread2---------3
  num is value +===thread1---------4
  num is value +===thread2---------5
  num is value +===thread1---------6
  num is value +===thread1---------7
  num is value +===thread2---------7
  很明显是错误的,应为两个线程共享同一个变量。这里就是变量的安全问题。
  解决办法:
  1抛弃单实例,多线程的方式,用多实例,多线程的方式,这样就和单线程是一个样了,不会出错,但是是最接近传统的编程模式
  2不要用类的实例变量,经可能把变量封装到方法内部。
  1类的解决办法的代码。
  Java代码
  public class TestMan {
  public static void main(String[] args) {
  Runnable safe=new ThreadSafe();
  Runnable safe2=new ThreadSafe();
  Thread thread1=new Thread(safe,"thread1");
  Thread thread2=new Thread(safe2,"thread2");
  thread1.start();
  thread2.start();
  }
  }
  运行结果
  num is value +===thread1---------2
  num is value +===thread2---------2
  num is value +===thread1---------3
  num is value +===thread2---------3
  num is value +===thread1---------4
  num is value +===thread2---------4 [NextPage] 2类解决办法的代码

  Java代码

  public class ThreadSafe implements java.lang.Runnable {

  public void run() {

  int num = 1;

  for (int i = 0; i < 3; i++) {

  num = num + 1;

  try {

  Thread.sleep(2000);

  } catch (InterruptedException e) {

  e.printStackTrace();

  }

  System.out.println("num is value +==="+Thread.currentThread().getName()+"---------" + num);

  }

  }

  }

  Java代码

  public class TestMan {

  public static void main(String[] args) {

  Runnable safe=new ThreadSafe();

  Thread thread1=new Thread(safe,"thread1");

  Thread thread2=new Thread(safe,"thread2");

  thread1.start();

  thread2.start();

  }

  }

  运行结果

  num is value +===thread2---------2

  num is value +===thread1---------2

  num is value +===thread1---------3

  num is value +===thread2---------3

  num is value +===thread1---------4

  num is value +===thread2---------4

  这两种办法,比较推荐适用第二个办法,就是把变量经可能的封装到风发内部,这样他们就是线程的私有变量了。另外,从jdk1.2后,推出了 threadlocal 对象,它作为线程的一个局部变量,可以为每个线程创建一个副本,用来保存每个线程的属性,各是各的,互不干扰。单每个 threadlocal变量只能保存一个变量,假如有多个变量要保存,那么就要写多个threadlocal对象。

  我们把代码改写一下。

  Java代码

  public class ThreadSafe implements java.lang.Runnable {

  ThreadLocal<Integer> local=new ThreadLocal<Integer>();

  public void run() {

  for (int i = 0; i < 3; i++) {

  if(local.get()==null){

  local.set(new Integer(1));

  }

  int num=local.get().intValue();

  num=num+1;

  local.set(new Integer(num));

  try {

  Thread.sleep(2000);

  } catch (InterruptedException e) {

  e.printStackTrace();

  }

  System.out.println("num is value +==="+Thread.currentThread().getName()+"---------" + local.get().intValue());

  }

  }

  }

  Java代码

  public class TestMan {

  public static void main(String[] args) {

  Runnable safe=new ThreadSafe();

  Thread thread1=new Thread(safe,"thread1");

  Thread thread2=new Thread(safe,"thread2");

  thread1.start();

  thread2.start();

  }

  }

  public class TestMan {

  public static void main(String[] args) {

  Runnable safe=new ThreadSafe();

  Thread thread1=new Thread(safe,"thread1");

  Thread thread2=new Thread(safe,"thread2");

  thread1.start();

  thread2.start();

  }

  }

 [NextPage] 2类解决办法的代码

  Java代码

  public class ThreadSafe implements java.lang.Runnable {

  public void run() {

  int num = 1;

  for (int i = 0; i < 3; i++) {

  num = num + 1;

  try {

  Thread.sleep(2000);

  } catch (InterruptedException e) {

  e.printStackTrace();

  }

  System.out.println("num is value +==="+Thread.currentThread().getName()+"---------" + num);

  }

  }

  }

  Java代码

  public class TestMan {

  public static void main(String[] args) {

  Runnable safe=new ThreadSafe();

  Thread thread1=new Thread(safe,"thread1");

  Thread thread2=new Thread(safe,"thread2");

  thread1.start();

  thread2.start();

  }

  }

  运行结果

  num is value +===thread2---------2

  num is value +===thread1---------2

  num is value +===thread1---------3

  num is value +===thread2---------3

  num is value +===thread1---------4

  num is value +===thread2---------4

  这两种办法,比较推荐适用第二个办法,就是把变量经可能的封装到风发内部,这样他们就是线程的私有变量了。另外,从jdk1.2后,推出了 threadlocal 对象,它作为线程的一个局部变量,可以为每个线程创建一个副本,用来保存每个线程的属性,各是各的,互不干扰。单每个 threadlocal变量只能保存一个变量,假如有多个变量要保存,那么就要写多个threadlocal对象。

  我们把代码改写一下。

  Java代码

  public class ThreadSafe implements java.lang.Runnable {

  ThreadLocal<Integer> local=new ThreadLocal<Integer>();

  public void run() {

  for (int i = 0; i < 3; i++) {

  if(local.get()==null){

  local.set(new Integer(1));

  }

  int num=local.get().intValue();

  num=num+1;

  local.set(new Integer(num));

  try {

  Thread.sleep(2000);

  } catch (InterruptedException e) {

  e.printStackTrace();

  }

  System.out.println("num is value +==="+Thread.currentThread().getName()+"---------" + local.get().intValue());

  }

  }

  }

  Java代码

  public class TestMan {

  public static void main(String[] args) {

  Runnable safe=new ThreadSafe();

  Thread thread1=new Thread(safe,"thread1");

  Thread thread2=new Thread(safe,"thread2");

  thread1.start();

  thread2.start();

  }

  }

  public class TestMan {

  public static void main(String[] args) {

  Runnable safe=new ThreadSafe();

  Thread thread1=new Thread(safe,"thread1");

  Thread thread2=new Thread(safe,"thread2");

  thread1.start();

  thread2.start();

  }

  }

广告合作:400-664-0084 全国热线:400-664-0084
Copyright 2010 - 2017 www.my8848.com 珠峰网 粤ICP备15066211号
珠峰网 版权所有 All Rights Reserved