黑马程序员_java基础加强7_多线程加强

来源:互联网 发布:巢湖学院网络选修课 编辑:程序博客网 时间:2024/05/19 20:38

---------------------- android培训、java培训、期待与您交流! ----------------------




2. 定时器的使用:

Timer相关用法:

Timer()    创建一个新计时器。

Timer(boolean isDaemon)  创建一个新计时器,可以指定其相关的线程作为守护程序运行。

Timer(String name) 创建一个新计时器,其相关的线程具有指定的名称。

Timer(String name, boolean isDaemon)   创建一个新计时器,其相关的线程具有指定的名称,并且可以指定作为守护程序运行。

 

void cancel()   终止此计时器,丢弃所有当前已安排的任务。

int purge()   从此计时器的任务队列中移除所有已取消的任务。

void schedule(TimerTask task, Date time)   安排在指定的时间执行指定的任务。

void schedule(TimerTask task, Date firstTime, longperiod)

          安排指定的任务在指定的时间开始进行重复的固定延迟执行。

void schedule(TimerTask task, long delay)    安排在指定延迟后执行指定的任务。

void schedule(TimerTask task, long delay, long period)

          安排指定的任务从指定的延迟后开始进行重复的固定延迟执行。

void scheduleAtFixedRate(TimerTask task, Date firstTime,long period)

          安排指定的任务在指定的时间开始进行重复的固定速率执行。

void scheduleAtFixedRate(TimerTask task, long delay,long period)

          安排指定的任务在指定的延迟后开始进行重复的固定速率执行。

 

说明:每隔两秒输出booming,然后隔4秒输出booming,再隔两秒输出booming,然后隔4秒输出booming,

如此交替输出。

public class TraditionalTimerTest {

    private static int count = 0;

    public static void main(String[] args) {

        new Timer().schedule(new MyTimerTask(), 2000);

    }

    static class MyTimerTask extends TimerTask{

        public void run() {

            count = (count+1)%2;

            System.out.println("bombing!");

            System.out.println(new Date());

            new Timer().schedule(new MyTimerTask(),1000+1000*count);

        }

    }

}

3.wait、notify、notifyAll这三个方法必须由同步监视器对象来调用。

Notify是随机唤醒一个线程。

在没有被通知、中断或超时的情况下,线程还可以唤醒一个所谓的虚假唤醒(spurious wakeup)。虽然这种情况在实践中很少发生,但是应用程序必须通过以下方式防止其发生,即对应该导致该线程被提醒的条件进行测试,如果不满足该条件,则继续等待。换句话说,等待应总是发生在循环中,如下面的示例:

synchronized (obj) {

while (<condition does nothold>)

obj.wait(timeout);

... // Perform actionappropriate to condition

     }

子线程循环10次,接着主线程循环100次,再子线程循环10次,接着主线程循环100次,如此重复50次。注意编程构造方法。

public class TraditionalThreadCommunication {

    public static void main(String[] args) {     

        final Business business =new Business();

        new Thread(

                new Runnable() {                 

                    @Override

                    public void run() {

                   

                        for(int i=1;i<=50;i++){

                            business.sub(i);

                        }                      

                    }

                }

        ).start();

        for(int i=1;i<=50;i++){

            business.main(i);

        }

    }

}

//封装资源

  class Business {

      private boolean bShouldSub = true;

      public synchronized void sub(int i){

          while(!bShouldSub){

              try {

                this.wait();

            } catch (InterruptedException e) {

                e.printStackTrace();

            }

          }

            for(int j=1;j<=10;j++){

            System.out.println("sub thread: " + j + ",loop of " + i);

            }

          bShouldSub = false;

          this.notify();

      }  

      public synchronized void main(int i){

            while(bShouldSub){

                try {

                    this.wait();

                } catch (InterruptedException e) {

                    e.printStackTrace();

                }

            }

            for(int j=1;j<=100;j++){

            System.out.println("main thread: " + j +",loop of " + i);

            }

            bShouldSub = true;

            this.notify();

      }

  }

上例类设计原则:要上锁的代码放在资源内部,不是线程代码中。

 

4.线程范围类的数据共享类ThreadLocal:用于实现线程内的数据共享,即多个模块在同一个线程中运行时要共享一份线程内的数据。如:购物车中,支付模块,购买物品模块共享同一个购物车实例。在每个购物车中数据都不相同,一个购物车相当于启动一个线程。

示例:

以下程序中,模块A和B都用于打印各自线程内的数据。每个线程内产生的数据都不相同。

import java.util.Random;

public class TreadScopeDataShare {

staticThreadLocal<ThreadData>threadLocal=

                                       new ThreadLocal<ThreadData>();

    public static void main(String[] args) {

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

            new Thread(new Runnable(){

                @Override

                public void run() {

                    int a=new Random().nextInt(100);

                    ThreadData user=new ThreadData();

                    user.setName("name"+a);

                    user.setAge(a);

                    threadLocal.set(user);

                    System.out.println(a +" is put into

                             "+Thread.currentThread().getName());

                    new ModuleA(threadLocal).printUser();

                    new ModuleB(threadLocal).printUser();

                    }   }).start();}}}

class ThreadData{

    private String name;

    private int age;

    public String getName() {returnname;}

    public void setName(String name) {this.name = name;}

    public int getAge() {returnage;}

    public void setAge(int age) {this.age = age;}}

//模块用于输出变量

class ModuleA{

    ThreadLocal<ThreadData> a=new ThreadLocal<ThreadData>();

    publicModuleA(ThreadLocal<ThreadData> a) {

        this.a=a;}

    public void printUser(){

        ThreadData user=a.get();

        System.out.println(Thread.currentThread().getName()+" 

                        ModuleA print  name:"+

                       user.getName()+"  age:"+user.getAge());}}

 

class ModuleB{

    ThreadLocal<ThreadData> a=new ThreadLocal<ThreadData>();

    publicModuleB(ThreadLocal<ThreadData> a) {

        this.a=a;}

    public void printUser(){

        ThreadData user=a.get();

        System.out.println(Thread.currentThread().getName()+"

                          ModuleB print  name:"+

                          user.getName()+"  age:"+user.getAge());}

在实际开发中, 通常将一个ThreadLocal绑定到一个线程中,即线程数据类的设计方法如下:

class ThreadData{

    private static ThreadLocal<ThreadData> map =

                                       new ThreadLocal<ThreadData>();

    private String name;

    private int age;

    private ThreadData() {   }

    public static ThreadDatagetThreadInstance() {

        ThreadDatainstance = map.get();

        if (instance == null) {

            instance = new ThreadData();

            map.set(instance);       }

        return instance;  }

    public String getName() {returnname;}

    public void setName(String name) { this.name = name;}

    public int getAge() {    returnage;}

    public void setAge(int age) {  this.age = age;}}





---------------------- android培训、java培训、期待与您交流! ----------------------

详细请查看:http://edu.csdn.net/heima

原创粉丝点击