线程知识总结(2)

来源:互联网 发布:手机突然连不上4g网络 编辑:程序博客网 时间:2024/05/16 00:33

定时器调度:

1.创建一个简单的定时器:
   
package com.rain.timer;import java.util.Timer;import java.util.TimerTask;public class TimerDemo1 {public static void main(String[] args) {new Timer().schedule(new TimerTask() {//匿名内部类public void run() {System.out.println("hahha");}},//四秒后开始执行,以后每两秒执行一次    4000,    2000);}}
2.创建一个复杂的定时器,定时器完成2秒4秒交替循环运行
package com.rain.timer;import java.util.Date;import java.util.Timer;import java.util.TimerTask;public class TimerDemo2 {public static void main(String[] args) throws Exception {/*需求:创建一个定时器,两秒之后开始运行,以后每隔两秒和四秒运行一次           思考:如果是两秒之后开始运行,并且以后都是两秒以后运行一次,这个时候可以用schedule方法完成          思路:创建一个定时器,创建一个定时器任务。在定时器任务中创建定时器,定时器中自我调用定时器任务                   此时就解决了循环运行的问题。每隔两秒或者四秒可以用运行的次数进行控制    */new Timer().schedule(new MyTimerTask(),1000);// 计时器while(true){Thread.sleep(1000);System.out.println(new Date().getSeconds()+"秒");}}}class MyTimerTask extends TimerTask{    public static int count=1;public void run() {count=(count+1)%2;// 保证count的值是1或者0System.out.println("bombing!!!!!!!!!!!");//在此方法中创建一个定时器吗,由此方法本身的调new Timer().schedule(new MyTimerTask(),2000+2000*count);}}

3 在实现负载的调度时候可以使用开源quartz。

实现线程范围内的共享变量

问题的引出,如下代码:
package com.rain.localthread;import java.util.Random;public class ThreadLocalDemo {public static int data=0;public static void main(String[] args) {// 创建两个线程同时操作同一份数据//for (int i = 0; i < 2; i++) {new Thread(new Runnable() {public void run() {data=new Random().nextInt(100);System.out.println(Thread.currentThread().getName()+"产生的数据:"+data);}}).start();//}new A(data).getData();new B(data).getData();}}class A{private int data;public A(int data){this.data=data;}public void getData(){System.out.println("A得到了数据为:"+data);}}class B{private int data;public B(int data){this.data=data;}public void getData(){System.out.println("B得到了数据为:"+data);}}

以上的代码中,多个模块(此处为A类和B类)在单个线程中共享一个数据的时候(此处为data)能够实现此功能,但是如果要是多个模块共享多个线程其中之一个线程的中数据该如何做到呢?
package com.rain.localthread;import java.util.LinkedHashMap;import java.util.Map;import java.util.Random;public class ThreadShareScope {//public static int data=0;public static Map<Thread,Integer> map=new LinkedHashMap<Thread,Integer>(); public static void main(String[] args) {for (int i = 0; i < 2; i++) {new Thread(new Runnable() {public void run() {int data=new Random().nextInt(100);System.out.println(Thread.currentThread().getName()+"has already produces"+data);map.put(Thread.currentThread(), data);new B().getData();new A().getData();}}).start();}}static class A{public void getData(){int data =map.get(Thread.currentThread());System.out.println("A"+Thread.currentThread().getName()+"产生的数据:"+data);}}static class B{public void getData(){int data =map.get(Thread.currentThread());System.out.println("B"+Thread.currentThread().getName()+"产生的数据:"+data);}}}

运行map集合存储的方法就解决了,在有多个线程处理多个模块的时候,其中的各自每个线程中调用的各个模块数据实现了共享,而且每个线程中的数据相互独立不相干扰。
这种思想在多个线程同时去处理数据库中各自的数据,保证每个线程中各个模块进行操作的数据具有独立性,相互不干扰。这就是线范围内的共享变量。
如图所示:


ThreadLocal类实现线程范围内的共享变量:

java中专门拥有类解决这一方面的问题,他就是threadlocal类,此类的实现的原理个Map集合相类似,默认的key值(key为上当前的线程currentThread)隐藏,只对外暴露set()和get()方法(相当于Map集合中设置和获取value的值,key则默认为当前线程),
package com.rain.localthread;import java.util.Random;public class ThreadShareScope {//public static Map<Thread,Integer> map=new LinkedHashMap<Thread,Integer>(); public static void main(String[] args) {for (int i = 0; i < 2; i++) {new Thread(new Runnable() {public void run() {int data=new Random().nextInt();System.out.println(Thread.currentThread().getName()+"产生了数据"+data);/*此中,在得到Person实例,把ThreadLocal实例化的同时,把Person的实例也加入了ThreadLocal中,一举三得,直接就可以设置属性     在此引入了一个关于集合的小插曲     在把一个实例加入集合之后还能对实例的方法进行调用,这样起作用吗?  List<Person> list=new ArrayList<Person>();  Person p=new Person();  list.add(p);  p.setName("aaaa");// 这里打印出了aaaa而不是空,说明先把实例加入集合,然后再设置实例的属性是行得通的  System.out.println(list.get(0).getName()); *  *  *  */Person p=Person.getThreadInstance();p.setAge(23+data);p.setName("chengyu"+data);new A().getData();new B().getData();}}).start();}}static class A{public void getData(){// 因为都是同一个Person实例对象,而且是在同一个线程。这两个条件就保证了数据在线程范围内的共享Person p=Person.getThreadInstance();System.out.println("A"+Thread.currentThread().getName()+"产生的数据:"+p.getAge()+":"+p.getName());}}static class B{public void getData(){Person p=Person.getThreadInstance();System.out.println("B"+Thread.currentThread().getName()+"产生的数据:"+p.getAge()+":"+p.getName());}}}//class Person{// 定义一个javabean,把要传输的数据封装到此类中,// 同时此类也封装了ThreadLocal的实例,用于控制线程没数据实现共享// 实现依据与实现单例类似private static ThreadLocal<Person> threadlocal=new ThreadLocal<Person>();public static Person getThreadInstance(){Person p=threadlocal.get();if(p==null){p=new Person();threadlocal.set(p);}return p;}private String name;private int age;public Person() {super();// TODO Auto-generated constructor stub}public Person(String name, int age) {super();this.name = name;this.age = 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;}}
以上代码中运用了ThreadLocal类,并且把ThreadLocal的创建封装到了传输数据的类中。
当每个线程在各个模块中都共享多个数据时,便可以把这多个数据封装到一个类中(上面的Person类),并且把ThreadLocal的创建封装到了传输数据的类中
在每个线程中可以得到类Person的实例,通过实例的set()方法把数据封装到Person中,
在向各个模块进行数据传输的时候,可以在各个模块中得到Person对象,通过Person类中的get()方法得到同一个线程所共享的数据。




原创粉丝点击