您的位置:首页 > 职场人生

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

2012-03-27 13:48 495 查看
---------------------- 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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: