线程高级操作笔记和练习

 

练习:主线程,子线程互相交互:


package cn.itcast.thread;
public class TestSubMainThread {
 private static boolean flag = true;
 
 public static void main(String[] args) {
  final Business business = new Business();
  new Thread(new Runnable() {
   @Override
   public void run() {
    for (int i = 0; i < 20; i++) {
     business.sub(i);
    }
   }
  }).start();
  for (int i = 0; i < 20; i++) {
   business.main(i);
  }
 }
 private static void business() {
  new Thread(new Runnable() {
   @Override
   public void run() {
    for (int i = 0; i < 20; i++) {
     synchronized (TestSubMainThread.class) {
      try {
       if (flag)
        TestSubMainThread.class.wait();
      } catch (InterruptedException e) {
       // TODO Auto-generated catch block
       e.printStackTrace();
      }
      for (int j = 0; j < 50; j++) {
       System.out.println(Thread.currentThread().getName()
         + "sub---" + j + "of " + i);
      }
      flag = !flag;
      TestSubMainThread.class.notify();
     }
    }
   }
  }).start();
  for (int i = 0; i < 20; i++) {
   synchronized (TestSubMainThread.class) {
    if (!flag) {
     try {
      TestSubMainThread.class.wait();
     } catch (InterruptedException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
     }
    }
    for (int j = 0; j < 10; j++) {
     System.out.println(Thread.currentThread().getName()
       + "main---" + j + "of " + i);
    }
    flag = !flag;
    TestSubMainThread.class.notify();
   }
  }
 }
}

 
package cn.itcast.thread;
public class Business {
 private boolean flag = true;
 public synchronized void sub(int i) {
  while (flag) {
   try {
    this.wait();
   } catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   }
  }
  for (int j = 0; j < 50; j++) {
   System.out.println(Thread.currentThread().getName() + "sub " + j
     + "loop of " + i);
  }
  flag = !flag;
  this.notify();
 }
 public synchronized void main(int i) {
  while (!flag) {
   try {
    this.wait();
   } catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   }
  }
  for (int j = 0; j < 10; j++) {
   System.out.println(Thread.currentThread().getName() + "main " + j
     + "loop of " + i);
  }
  flag = !flag;
  this.notify();
 }
}
这个代 是自己写的,心得体会:
线程的启动和线程需要执行的代 应该要进行分离,同时如果需要被线程执行的代 要解决安全问题,我们应该在内部解决,也就是当成一个业务来做,用户只要直接使用,即使在多线程情况也不会出现安全问题,这充分体现了面向对象的封装性,也即软件工程思想的高类聚思想;
这个练 主要是要求我们对线程的通信机制有一个比较透彻的了解,等待唤醒机制,注意到什么时候该等待,什么时候该改变 记,什么时候该唤醒对方。
线程范围的数据:ThreadLocal,该类的底层实现原理是,有一个Map集合,用于存储数据,以Thread对象为关键字,以数据为value;
 此设置时只要设置数据即可,即threadLocal.set(data);//将数据绑定到线程上;
取出操作threadLocal.get();//取出当前线程绑定的数据;
 据这个思路我们想,我们是否可以设计出一个跟当前线程相关的实例对象,在该实例对象中存储数据,取出数据;
这个我们可以从单例设计模式中的懒汉式中得到启发;
判断某个线程上是否存在数据(实例对象);如果有怎返回这个实例对象,我们得到了绑定到某个线程的实例对象,用该对象进行存取数据的操作;如果返回的是空,那么我们就创建一个实例对象,然后绑定到某个线程;当然依 的是ThreadLocal对象;
代 如下:


用面向对象的思想来看,这种设计体现了封装性,用户使用时直接就可以获取到和线程绑定的实例对象;
struts2就是 据这个原理来解决线程安全问题的,他针对每一个请求都创建一个action,将所有和该请求相关的数据和对象封装到一个action中,然后将这个action绑定到当前线程;请求一结束就摧毁;
 package cn.itcast.threadlocal;
public class ThreadLocalInstance {
 private String name;
 private int age;
 public ThreadLocalInstance() {
  super();
 }
 private final static ThreadLocal map = new ThreadLocal();
 private static ThreadLocalInstance instance = null;
 public static ThreadLocalInstance getInstance() {
  instance = map.get();
  if (instance == null) {
   instance = new ThreadLocalInstance();
   map.set(instance);
  }
  return instance;
 }
 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;
 }
}


ActionContext类的设计就是这样滴;
同时我们应该清楚ThreadLocal并不是真正的解决了线程安全问题,只是他给每个线程都copy一个共享数据的副本;
因此类似于单线程;
线程高级操作笔记和练习 转发至微博
 
线程高级操作笔记和练习 转发至微博
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值