快精灵印艺坊 您身边的文印专家
广州名片 深圳名片 会员卡 贵宾卡 印刷 设计教程
产品展示 在线订购 会员中心 产品模板 设计指南 在线编辑
 首页 名片设计   CorelDRAW   Illustrator   AuotoCAD   Painter   其他软件   Photoshop   Fireworks   Flash  

 » 彩色名片
 » PVC卡
 » 彩色磁性卡
 » 彩页/画册
 » 个性印务
 » 彩色不干胶
 » 明信片
   » 明信片
   » 彩色书签
   » 门挂
 » 其他产品与服务
   » 创业锦囊
   » 办公用品
     » 信封、信纸
     » 便签纸、斜面纸砖
     » 无碳复印纸
   » 海报
   » 大篇幅印刷
     » KT板
     » 海报
     » 横幅

Java入门笔记6_线程

1. 多线程
1.1 创建线程类
在Java中可以简朴的从Thread类中继续创建自己的线程类:

public class MyFirstThread extends Thread {

public void run() { . . .}

}

说明:

(1) Thread类位是java.lang包中,所以可以不用显示import;

(2) 从Thread类中继续下来的类最好重载run()方式,以运行需要的代码;

可以按以下方式实例化并运行线程:

MyFirstThread aMFT = new MyFirstThread();

aMFT.start();

说明:

(3) 实例化线程类后,系统会初始化一些参数,主要是为线程创建名称,把新的线程加入指定的线程组,初始化线程运行需要的内存空间,指定新线程的优先级别,指定它的守候线程;

(4) start方式是Thread类中的方式,它会调用run方式,在新的线程中运行指定的代码;

(5) 除了start方式外,从Thread继续下来的类还具有其它一些主要的方式:stop,suspend,resume等;

以下是一个完整的Thread派生类:

1: public class ComplexThread extends Thread {

2: private int delay;

3:

4: ComplexThread(String name, float seconds) {

5: super(name);

6: delay = (int) seconds * 1000; // delays are in milliseconds

7: start(); // start up ourself!

8: }

9:

10: public void run() {

11: while (true) {

12: System.out.println(Thread.currentThread().getName());

13: try {

14: Thread.sleep(delay);

15: } catch (InterruptedException e) {

16: return;

17: }

18: }

19: }

20:

21: public static void main(String argv[]) {

22: new ComplexThread("one potato", 1.1F);

23: new ComplexThread("two potato", 1.3F);

24: new ComplexThread("three potato", 0.5F);

25: new ComplexThread("four", 0.7F);

26: }

27: }

1.2 Runable接口
创建多线程运行指定代码的另一种方式是,在创建类时implement Runable这个接口:

public class MySecondThread extends ImportantClass implements Runnable {

public void run() {. . .}

}

说明:

(1) 该类implement Runable接口,就表明有意图运行在单独的线程中,Thread也是implement Runable接口的;

(2) Implement Runalbe接口至少需要实现run方式;

以下是创建新线程运行该类的实例:

MySecondThread aMST = new MySecondThread();

Thread aThread = new Thread(aMST);

aThread.start();

说明:

(3) Thread类有多个构造函数Thread()、Thread(Runable target)等,本例中用的就是第二个构造函数,它有一个Runable类型的函数,所以要在多线程中运行的实例的类必须是implement Runable的;

(4) AThead.start()方式调用Thread实例的中的target.run方式,本例中就是MySecondThread实例中的run方式;

(5) Thread构造函数还可以指定线程名,运行所需的stack,线程所属的组等;

为了防止线程非正常结束,需要将start方式置入try…catch中,如:

try{

myThread.start();

}catch(ThreadDeath aTD){

System.out.println("end Thread");

throw aTD;

}

在这个例子中将捕捉ThreadDeath非常,处理后重新抛出该非常,以便Java执行stop方式,进行资源等清理工作。

1.3 线程的优先级
多个线程的执行是有一定的优先级别的,对于下面这个例子:

public class RunnablePotato implements Runnable {

public void run() {

while (true)

System.out.println(Thread.currentThread().getName());

}}

public class PotatoThreadTester {

public static void main(String argv[]) {

RunnablePotato aRP = new RunnablePotato();

Thread T1 = new Thread(aRP, "one potato");

Thread T2 = new Thread(aRP, "two potato");

T1.start();

T2.start();

}}

对于非抢占式的系统,上例中的第一个线程会一直运行,第二个线程没有机会运行;对于抢占式的系统,这二人线程会交替运行。

为了让多线程在非抢占式中运行,最好在run方式中加入以下语句:

Thread.yield()





public void run() {

while (true)

System.out.println(Thread.currentThread().getName());

Thread.yield()

}

Thread.yield会将当前线程暂时让位一小段时间,让其它的线程有机会运行,过了这段时间后,该线程继续运行。上述功能也可以用Thread.sleep()方式实现。

在Java中有优先级别可以从1到10,其中1可以用Thread.MIN_PRIORITY表示,5可以用Thread.NORM_PRIORITY,10可以用Thread.MAX_PRIORITY表示,新建一个线程默认的级别是Thread.NORM_PRIORITY。也可以使用setPriority方式改变线程的优先级别,如T1.setPriority(T2.getPriority + 1)。

与yield方式相反的是join方式,它表示一直要等到指定的线程运行完毕,如:

try{ t.join();} catch (InterruptedException ignored) { }

表示要等到线程t运行完毕后,再执行下一步操作。这种情况比较少见。

1.4 synchronized
为了保证某个方式或者对象某个时刻只能被一个方式访问,那就需要使用synchronized要害字。

如:

public synchronized void countMe() {

crucialValue += 1;

}

就表示countMe这个方式中的操作是一个原子操作,+= 要执行三个步骤,使用synchronized后,这三个步骤是具有原子性,即在三个步骤完成前,其它对于crucialValue的访问都将被拒绝,即可保证countMe的线程安全。

另一个例子:

synchronized(p) {

safeX = p.x();

safeY = p.y();

}

表示在block范围内锁定p对象,不许其它程序修改p对象中的值。

以上代码的作用都是保护某个对象内的变量不能同时被多个线程访问,下面介绍如何保护class variable的线程安全:

public class StaticCounter {

private static int crucialValue;



public void countMe() {

synchronized(getClass()) {

crucialValue += 1;

} } }

说明:

(1) 在这个例子中,crucialValue是private并且static,这表示它可以被该类的所有实例访问;

(2) synchronized使用getClass方式获取类名,而不能直接使用StaticCounter

(3) 假如crucialValue是public的,那么修改代码成:

synchronized(Class.forName("StaticCounter")) {

StaticCounter.crucialValue += 1;

}





返回类别: 教程
上一教程: javamail的几个实用知识点
下一教程: 漫谈Java数据库存取技术

您可以阅读与"Java入门笔记6_线程"相关的教程:
· Java入门笔记5_非常
· 《Java 手机/PDA 程序设计入门》读书笔记8--LCDAUI低级API之 线程 时间控制
· Java入门笔记7_Stream
· Java入门笔记2_Applet
· Java入门笔记1_HelloWorld
    微笑服务 优质保证 索取样品