二、创建线程的几种方式

一、使用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 Runnable
		new Thread(myRunnable).start();
		Thread t1=new Thread(myRunnable);
		t1.start();
		Thread t2=new Thread(myRunnable);
		t2.start();
		
	}
}

class MyRunnable implements Runnable{
	@Override
	public 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(){
			@Override
			public 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(){
			@Override
			public void run() {//Runnable中的run方法
				System.out.println("Runnable中的run方法");
			}
		}){
			@Override
			public void run() {//Thread中的run方法
				System.out.println("Thread中的run方法");
			}
		}.start();
	}
}





  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

FlyingZCC

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值