二、创建线程的几种方式

来源:互联网 发布:程序员教程 第4版 pdf 编辑:程序博客网 时间:2024/06/07 09:57
一、使用Thread创建线并启动线程java.lang.Thread类是线程类,其每一个实例表示一个可以并发运行的线程。我们可以通过继承该类并重写run方法来定义一个具体的线程。其中重写run方法的目的是定义该线程要执行的逻辑。启动线程时调用线程的start()方法而非直接调用run()方法。start()方法会将当前线程纳入线程调度,使当前线程可以开始并发运行。当线程获取时间片段后会自动开始执行run方法中的逻辑。

package com.zc;//模拟售票窗口.100张票.3个窗口卖.有线程安全问题public class T03Window {public static void main(String[] args){Window window1=new Window();Window window2=new Window();Window window3=new Window();window1.setName("窗口1");window2.setName("窗口2");window3.setName("窗口3");window1.start();window2.start();window3.start();}}class Window extends Thread{static int ticket=100;public void run(){while(true){if(ticket>0){try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName()+"售票号为:"+ticket--);}else{break;}}}}
其中Window类继承Thread类,重写Thread类中的run方法,里面是具体的业务逻辑。通过调用start()方法启动线程。

Thread类中的run()方法private Runnable target;//原本的run()方法啥事也没干,所以创建线程时,重写该方法  @Override    public void run() {        if (target != null) {            target.run();        }    }
如果target不为null,则运行target对象的run()方法

Thread类中可以传入Runnable对象的构造方法

 public Thread(Runnable target) {    init(null, target, "Thread-" + nextThreadNum(), 0);}
该方法会调用init方法,给target赋值
private void init(){....  this.target = target;  ...}   
此时run方法就会执行target.run();

二、所以第二种创建线程的方式为使用Runnable创建并启动线程

实现Runnable接口并重写run方法来定义线程体,然后在创建线程的时候将Runnable的实例传入并启动线程。
这样做的好处在于可以将线程与线程要执行的任务分离开减少耦合,同时java是单继承的,定义一个类实现Runnable接口这样的做法可以更好的去实现其他父类或接口。因为接口是多继承关系。

package com.zc;//实现Runnable接口.创建多线程public class T04Runnable {public static void main(String[] args){MyRunnable myRunnable=new MyRunnable();//要想启动一个多线程.必须调用start()方法//Thread类的构造方法中.有一个Thread(Runnable target)//new Thread(..)对象的start()方法启动的是myRunnable对象的run()方法.底层源码.Runnable()接口只有run()方法//Thread类implements Runnablenew Thread(myRunnable).start();Thread t1=new Thread(myRunnable);t1.start();Thread t2=new Thread(myRunnable);t2.start();}}class MyRunnable implements Runnable{@Overridepublic void run() {for(int i=1;i<=100;i++){if(i%2==0){System.out.println(Thread.currentThread().getName()+":"+i);}}}}
三、创建线程就以上两种方式,继承Thread类或实现Runnable接口。当然使用匿名内部类创建线程会使得代码更加简洁。

package com.zc;//匿名内部类创建线程public class T02InnerThread {public static void main(String[] args){//继承于Thread类的匿名内部类对象new Thread(){@Overridepublic void run(){for(int i=1;i<=100;i++){if(i%2==0){System.out.println(Thread.currentThread().getName()+":"+i);}}}}.start();new Thread(){public void run(){for(int i=1;i<=100;i++){if(i%2!=0){System.out.println(Thread.currentThread().getName()+":"+i);}}}}.start();}}
四、最后若既重写了Thread类中的run方法的同时又实现了Runnable接口中的run方法,哪个run方法会执行。

package com.zc.zx;//输出结果为:"Thread中的run方法"//new Thread(){};创建了一个Thread的匿名内部类,//是Thread的子类,其中的run方法相当于重写了父类中的run方法,所以理应执行外面的run()//如果没有重写run(),会调用父类Thread中的run方法,此时target不为null,则会执行runnable里的run()public class T02WhichRun {public static void main(String[] args) {new Thread(new Runnable(){@Overridepublic void run() {//Runnable中的run方法System.out.println("Runnable中的run方法");}}){@Overridepublic void run() {//Thread中的run方法System.out.println("Thread中的run方法");}}.start();}}





0 0
原创粉丝点击