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

原创 2012年03月27日 13:48:40

---------------------- 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() {return name;}

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

    public int getAge() {return age;}

    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() {return name;}

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

    public int getAge() {    return age;}

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





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

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

版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

黑马程序员----------java基础加强之多线程、单例设计模式

----------------------android培训、java培训、期待与您交流! ---------------------- 虽然老师

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

---------------------- android培训、java培训、期待与您交流! ---------------------- 1.创建线程的两种方式:  ...

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

---------------------- android培训、java培训、期待与您交流! ---------------------- 8.用Lock实现线程间的通信:...

黑马程序员--java基础--多线程

创建线程 继承Thread类 建线程的第一种方式:继承Thread类. 步骤如下: 1 继承Thread类 2 覆写Thread类中的run方法 3 调用线程的start方法,这个方法有两个作用:  ...

黑马程序员——Java基础__多线程(上)

面向对象——多线程(上) 简单概念:任务管理器——进程里面执行的程序里面就有很多的线程,不是同时执行的,只是CPU在做着快速的切换。 什么是API?就是Java用面向对象的思想给程序员封装...

黑马程序员_java基础_多线程

------- android培训、java培训、期待与您交流!--------- 多线程 一、多线程的概述       要理解多线程,就必须理解线程。而要理解线程,就必须知道进程。 ...

黑马程序员—10—java基础:有关多线程安全的学习笔记和学习心得体会

------- android培训、java培训、期待与您交流! ---------- 1. 通过实例解说多线程安全:    class Ticket implements Runnabl...

黑马程序员——高新技术---Java基础-多线程1

1:要想了解多线程,必须先了解线程,而要想了解线程,必须先了解进程,因为线程是依赖于进程而存在。   2:什么是进程? 通过任务管理器我们就看到了进程的存在。 而通过观察,我们发现只有运行的程序才会出...

黑马程序员《java基础总结(六)》(多线程)

---------------------- ASP.Net+Android+IOS开发、.Net培训、期待与您交流! ----------------------  多线程: 进程:正在进...

黑马程序员—9—Java基础:有关多线程的学习笔记和学习心得体会

------- android培训、java培训、期待与您交流! ---------- 1.      进程与线程简介 a)        进程:一般来说就...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)