1.利用Thread的子类创建线程
例1.用Thread子类创建多线程程序。
先定义一个Thread的子类,该类的run方法只用来输出一些信息。
packagethread;public class myThread extendsThread{private static int count=0;public voidrun() {inti;for(i=0;i<100;i++){
count=count+1;
System.out.println("My name is "+getName()+" count="+count);try{
sleep(10);
}catch(InterruptedException e) {//TODO Auto-generated catch block
e.printStackTrace();
}
}
}publicmyThread(String name){super(name);
}
}
下面用程序来创建线程对象并运行该线程对象。
packagethread;public classmulThread {public static voidmain(String[] args) {
myThread trFirst,trSecond;
trFirst= new myThread("First Thread");
trSecond= new myThread("Second Thread");
trFirst.start();
trSecond.start();
System.out.println("主线程结束!");
}
}
2.实现Runnable接口创建线程
例2. 继承Runnable接口实现多线程。
packagethread;public class ThreadImRunable implementsRunnable{private static int count=0;privateThread t;public voidrun() {inti;for(i=0;i<100;i++){
count++;
System.out.println("My name is "+t.getName()+" count="+count);try{
t.sleep(10);
}catch(Exception e) {//TODO: handle exception
}
}
}publicThreadImRunable(String name){
t= new Thread(this,name);
}public voidstart(){
t.start();
}
}
主程序跟前面相同。
packagethread;public classmulThread {public static voidmain(String[] args) {
myThread trFirst,trSecond;
trFirst= new myThread("First Thread");
trSecond= new myThread("Second Thread");
trFirst.start();
trSecond.start();
System.out.println("主线程结束!");
}
}
3.使用isAlive()和join()等待子线程结束
例3. join()方法使用示例。
packagethread;public classdemoJoin {public static voidmain(String[] args){
myThread trFirst,trSecond;
trFirst= new myThread("First Thread");
trSecond= new myThread("Second Thread");try{
trFirst.start();
trSecond.start();
trFirst.join();
trSecond.join();
}catch(InterruptedException e) {
System.out.println("主线程被中断!");
}
System.out.println("主线程结束!");
}
}
4.设置线程优先级
例4. 设置线程优先级示例。
packagethread;public class clicker extendsThread{private int click=0;private volatile boolean running=true;//volatile告诉编译器,不要自作主张为它编译优化
public intgetClick(){returnclick;
}public voidrun() {while(running){
click= click + 1;
}
}public voidnormalStop(){
running= false;
}
}
程序中的循环变量running被声明成volatile,这个关键字告诉编译器,不要自作主张为它进行编译优化。
注意:不要将循环体中“click=click+1”改成“++click”的形式。对于前者,编译器会生成多条命令,执行过程中系统有机会将它中断。而后者只有一条指令,系统不能将其中断,这样其他进程就难以有机会使用CPU。
packagethread;public classdemoPri {public static voidmain(String[] args) {
clicker c1High,c2Low;
c1High=newclicker();
c2Low=newclicker();
c1High.setPriority(Thread.NORM_PRIORITY+2);
c2Low.setPriority(Thread.NORM_PRIORITY-2);
c2Low.start();
c1High.start();try{
Thread.sleep(1000);
}catch(InterruptedException e1) {//TODO Auto-generated catch block
e1.printStackTrace();
}
c1High.normalStop();
c2Low.normalStop();try{
c1High.join();
c2Low.join();
}catch(InterruptedException e) {//TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("c1High执行循环的次数为:"+c1High.getClick());
System.out.println("c2Low 执行循环的次数为:"+c2Low.getClick());
}
}
程序的输出结果为:
c1High执行循环的次数为:427835536c2Low 执行循环的次数为:396647205
结果表明,优先级高的线程获得了更多的CPU运行时间。
5.线程的互斥
例5. 线程互斥示例。
packagethread;public class mutixThread extendsThread{private static int count = 0;private synchronized static voidchange(Thread t){
count= count + 1;
System.out.println("My name is "+t.getName()+" count="+count);
}public voidrun() {inti;for(i=0;i<100;i++){
change(this);try{
sleep(10);
}catch(InterruptedException e) {//TODO Auto-generated catch block
e.printStackTrace();
}
}
}publicmutixThread(String name){super(name);
}
}
下面写一个程序测试它的运行情况。
packagethread;public classdemoMutix {public static voidmain(String[] args){
mutixThread t1,t2,t3;
t1= new mutixThread("First Thread");
t2= new mutixThread("Second Thread");
t3= new mutixThread("Third Thread");
t1.start();
t2.start();
t3.start();try{
t1.join();
t2.join();
t3.join();
}catch(InterruptedException e) {//TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("主线程结束");
}
}
程序运行结果如下:
.....
My name is Third Thread count=297My name is First Thread count=298My name is Third Thread count=299My name is Second Thread count=300主线程结束
6.线程的同步
例6. 线程同步示例。
packagethread;public classcommSource {static boolean flag = true;static intdata;static intcount;
}
packagethread;public class setDataThread extendsThread {private readDataThread otherThread=null; //存储另外一个线程对象
public voidrun(){for(int i=0;i<100;i++){if(!commSource.flag)try{synchronized(this){ //锁定当前对象
wait(); //阻塞自己
}
}catch(InterruptedException e) {//TODO Auto-generated catch block
e.printStackTrace();
}
commSource.flag= false;
commSource.data= (int)(Math.random()*1000);
commSource.count++;
System.out.println("设置数据:"+commSource.data+" count="+commSource.count);synchronized(otherThread){ //锁定另外一个线程对象
otherThread.notify(); //唤醒另外一个线程对象
}
}
}public voidsetOtherThread(readDataThread rt){
otherThread=rt;
}
}
packagethread;public class readDataThread extendsThread{private setDataThread otherThread = null;public voidrun(){for(int i=0;i<100;i++){if(commSource.flag)try{synchronized(this){
wait();
}
}catch(InterruptedException e) {//TODO Auto-generated catch block
e.printStackTrace();
}
commSource.flag= true;
System.out.println("获得数据:"+commSource.data);synchronized(otherThread){
otherThread.notify();
}
}
}public voidsetOtherThread(setDataThread st){
otherThread=st;
}
}
packagethread;public classdemoSynchorny {public static voidmain(String[] args) {
setDataThread str;
readDataThread rtr;
str=newsetDataThread();
rtr=newreadDataThread();
str.setOtherThread(rtr);
rtr.setOtherThread(str);
str.start();
rtr.start();
}
}
输出结果如下:
设置数据:295 count=1获得数据:295......
设置数据:974 count=99获得数据:974设置数据:526 count=100获得数据:526
两个线程是严格交替运行的。
7.暂停恢复和停止线程
例7. 自己编写线程的暂停、恢复和停止方法。
packagethread;public class enhanceThread extendsThread {private static final int STOP = 1;private static final int RUNNING = 2;private static final int SUSPEND = 3;private int state =STOP;public synchronized voidrun(){int cnt = 0;while(state!=STOP){if(state==SUSPEND){try{
wait();
}catch(InterruptedException e) {//TODO Auto-generated catch block
e.printStackTrace();
}
}++cnt;
System.out.println("线程正在运行:"+cnt);try{
sleep(100);
}catch(InterruptedException e) {//TODO Auto-generated catch block
e.printStackTrace();
}
}
}public voidnormalStop(){
state=STOP;
}public voidnormalSuspend(){
state=SUSPEND;
}//恢复线程运行
public synchronized voidnormalResume(){
state=RUNNING;
notify();
}publicenhanceThread(){
state=RUNNING;
}
}
packagethread;public classdemoEhanceThread {public static voidmain(String[] args) {
enhanceThread tr;
tr= newenhanceThread();
System.out.println("启动线程!");
tr.start();try{
Thread.sleep(1000);
System.out.println("将线程挂起!");
tr.normalSuspend();
Thread.sleep(1000);
System.out.println("恢复线程运行!");
tr.normalResume();
Thread.sleep(1000);
System.out.println("终止线程运行!");
tr.normalStop();
}catch(InterruptedException e) {//TODO Auto-generated catch block
e.printStackTrace();
}
}
}
输出结果如下:
启动线程!
线程正在运行:1线程正在运行:2线程正在运行:3线程正在运行:4线程正在运行:5线程正在运行:6线程正在运行:7线程正在运行:8线程正在运行:9线程正在运行:10将线程挂起!
恢复线程运行!
线程正在运行:11线程正在运行:12线程正在运行:13线程正在运行:14线程正在运行:15线程正在运行:16线程正在运行:17线程正在运行:18线程正在运行:19线程正在运行:20终止线程运行!
8.生产者-消费者问题实例
例8. 生产者-消费者实例。
packagethread;public classcommon {private int production[]; //存放产品的缓冲区
private int count; //产品的实际数目
private int BUFFERSIZE = 6; //缓冲区大小
publiccommon(){
production= new int[BUFFERSIZE];
count= 0;
}//从缓冲区中取数据
public synchronized intget(){intresult;while(count<=0)try{
wait();
}catch(InterruptedException e) {//TODO Auto-generated catch block
e.printStackTrace();
}
result= production[--count];
notifyAll();returnresult;
}//向缓冲区中写数据
public synchronized void put(intnewproduct){while(count>=BUFFERSIZE)try{
wait();
}catch(InterruptedException e) {//TODO Auto-generated catch block
e.printStackTrace();
}
production[count++]=newproduct;
notifyAll();
}
}
packagethread;//消费者线程
public class consumer extendsThread {privatecommon comm;publicconsumer(common mycomm){
comm=mycomm;
}public synchronized void run(){ //线程体
inti,production;for(i=1;i<=20;i++){ //消费线程计数
production =comm.get();
System.out.println("得到的数据为:"+production);try{
sleep(10);
}catch(InterruptedException e) {//TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
packagethread;//生产者线程
public class producer extendsThread {privatecommon comm;publicproducer(common mycomm){
comm=mycomm;
}public synchronized voidrun(){inti;for(i=1;i<=10;i++){
comm.put(i);
System.out.println("生产的数据为:"+i);try{
sleep(10);
}catch(InterruptedException e) {//TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
packagethread;public classproducer_consumer {public static voidmain(String[] args){
common comm= newcommon();
producer p1= newproducer(comm);
producer p2= newproducer(comm);
consumer c1= newconsumer(comm);
p1.start();
p2.start();
c1.start();
}
}
程序某次运行结果如下:
生产的数据为:1得到的数据为:1生产的数据为:1得到的数据为:2生产的数据为:2生产的数据为:2生产的数据为:3得到的数据为:3生产的数据为:3生产的数据为:4得到的数据为:4生产的数据为:4生产的数据为:5得到的数据为:5生产的数据为:5得到的数据为:5生产的数据为:6生产的数据为:6得到的数据为:6生产的数据为:7生产的数据为:8得到的数据为:7得到的数据为:8生产的数据为:9生产的数据为:10得到的数据为:9得到的数据为:10生产的数据为:7得到的数据为:7生产的数据为:8得到的数据为:8生产的数据为:9得到的数据为:9生产的数据为:10得到的数据为:10得到的数据为:6得到的数据为:4得到的数据为:3得到的数据为:2得到的数据为:1
结果表明,该程序已经很好地解决了生产者线程和消费者线程间的同步问题。