java多线程(1)- 线程创建

本文详细介绍了在Java中通过继承Thread类、实现Runnable接口和Callable接口创建多线程的方法,包括示例代码演示。从普通方法调用到并发下载任务,展示了多线程在操作系统中的应用和注意事项。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

程序,进程,线程
  • 在操作系统中进行的程序就是进程,即是说进程是程序的一次执行过程,如QQ,游戏等。
  • 一个进程可以有多个线程,比如在播放视频的时候可以同时听到声音,看到图像,弹幕等。
  • 每个进程至少有一个线程,线程是一条独立执行的路径,是cpu调度,执行的单位。
  • 多线程是指多个线程并发执行,如果在多cpu系统,并发可能是指多个线程同时执行,在单cpu系统中,并发指的是多个线程交替执行,在同一时间间隔内同时执行。
普通方法调用和多线程

在这里插入图片描述
在程序中main()为主线程,是系统的入口,用于执行整个程序。在普通方法调用中只有主线程一条执行路径;多线程则是有主线程和子线程多条执行路径。

java多线程创建
  1. 继承Thread类
  2. 实现Runnable接口
  3. 实现Callable接口

一.继承Thread类

  • 自定义线程类继承Thread类
  • 重写run()方法,编写线程执行体
  • 创建线程对象,调用start()方法启动线程
//创建方式一:继承Thread类,重写run()方法,调用start开启线程
public class testThread1 extends Thread{
    @Override
	public void run() {
    	//run方法线程体
    	for(int i = 0; i < 20; i++) {
    		System.out.println("子线程"+i);
    	}
    }
    
    public static void main(String[] args) {
    	//main主线程
    	
    	// 创建一个线程对象
    	testThread1 thread1 = new testThread1();
    	
    	//调用start()方法开启线程
    	thread1.start();
    	
    	for(int i = 0; i < 20; i++) {
    		System.out.println("主线程"+i);
    	}
    }
}

二.实现Runnable()接口

  • 定义线程类实现Runnable接口
  • 实现run()方法,编写线程执行体
  • 创建线程对象,调用start()方法启动线程
    利用接口实现多线程可以避免单继承的局限性,方便一个对象被多个线程使用。
//创建线程方式2:实现runnable接口,重写run方法,执行线程需要丢入runnable接口实现类,调用start方法
public class testThread3 implements Runnable {

	@Override
	public void run() {
    	//run方法线程体
    	for(int i = 0; i < 20; i++) {
    		System.out.println("子线程"+i);
    	}
    }
    
    public static void main(String[] args) {
    	//main主线程
    	
    	// 创建runnable接口的实现类对象
    	testThread3 thread3 = new testThread3();
    	//创建线程对象,通过线程对象来开启我们的线程,代理
    	Thread thread = new Thread(thread3);
    	
    	thread.start();
    	
    	for(int i = 0; i < 20; i++) {
    		System.out.println("主线程"+i);
    	}
    }

}

三.实现Callable接口

  • 实现Callable接口,需要返回值
  • 重写call方法,需要抛出异常
  • 创建目标对象
  • 创建执行服务:ExecutorService ser = Executors.NewFixedThreadPool(1);
  • 提交执行:Future result = ser.submit(t1);
  • 获取结果:boolean r1 = result.get();
  • 关闭服务:ser.shutdownNow();

第三个方式我们用一个例子来实现。这个例子是网图下载,我们需要用到一个别人写好的jar包,common-io包,到百度自行下载即可。在项目中导入jar包。首先我们先写个下载类:

//下载器
class WebDownloader{
	//下载方法
	public void downloader(String url,String name)  {
		try {
			FileUtils.copyURLToFile(new URL(url),new File(name));
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			System.out.println("io异常,dawnloader()方法错误");
		}
	}
}

接着写我们的主类

//创建方式三:实现Callable接口
public class ThreadCallable implements Callable<Boolean> {

	private String url;//网络图片地址
	private String name;//保存文件名
	
	public ThreadCallable(String url,String name) {
		this.url = url;
		this.name = name;
	}
	
	@Override
	public Boolean call() {
		WebDownloader webDownloader = new WebDownloader();
		webDownloader.downloader(url, name);
		System.out.println("下载文件名为:"+name);
		return true;
	}
	
    public static void main(String[] args) throws InterruptedException, ExecutionException {
    	ThreadCallable t1 = new ThreadCallable("https://image.baidu.com/search/detail?ct=503316480&z=0&ipn=false&word=%E7%94%B5%E8%84%91%E5%A3%81%E7%BA%B8&step_word=&hs=0&pn=0&spn=0&di=17930&pi=0&rn=1&tn=baiduimagedetail&is=0%2C0&istype=0&ie=utf-8&oe=utf-8&in=&cl=2&lm=-1&st=undefined&cs=1705581946%2C4177791147&os=3092380308%2C906356246&simid=4087421280%2C717844758&adpicid=0&lpn=0&ln=30&fr=&fmq=1601886433058_R&fm=&ic=undefined&s=undefined&hd=undefined&latest=undefined&copyright=undefined&se=&sme=&tab=0&width=undefined&height=undefined&face=undefined&ist=&jit=&cg=wallpaper&bdtype=0&oriquery=%E7%94%B5%E8%84%91%E5%A3%81%E7%BA%B8&objurl=http%3A%2F%2Fattachments.gfan.com%2Fforum%2F201503%2F19%2F211608ztcq7higicydxhsy.jpg&fromurl=ippr_z2C%24qAzdH3FAzdH3Fkkf_z%26e3B2uwg_z%26e3Bv54AzdH3Fwg165t1-0bb0c0c-swfp-8_z%26e3Bip4s&gsm=1&rpstart=0&rpnum=0&islist=&querylist=&force=undefined","1.jpg");
    	ThreadCallable t2 = new ThreadCallable("https://image.baidu.com/search/detail?ct=503316480&z=0&ipn=false&word=%E7%94%B5%E8%84%91%E5%A3%81%E7%BA%B8&step_word=&hs=0&pn=1&spn=0&di=144650&pi=0&rn=1&tn=baiduimagedetail&is=0%2C0&istype=0&ie=utf-8&oe=utf-8&in=&cl=2&lm=-1&st=undefined&cs=1262773730%2C4108667670&os=4089191533%2C296881675&simid=4196037961%2C729463796&adpicid=0&lpn=0&ln=30&fr=&fmq=1601886433058_R&fm=&ic=undefined&s=undefined&hd=undefined&latest=undefined&copyright=undefined&se=&sme=&tab=0&width=undefined&height=undefined&face=undefined&ist=&jit=&cg=wallpaper&bdtype=0&oriquery=%E7%94%B5%E8%84%91%E5%A3%81%E7%BA%B8&objurl=http%3A%2F%2Fb-ssl.duitang.com%2Fuploads%2Fitem%2F201603%2F04%2F20160304163044_Ze4ad.jpeg&fromurl=ippr_z2C%24qAzdH3FAzdH3Fooo_z%26e3B17tpwg2_z%26e3Bv54AzdH3Fks52AzdH3F%3Ft1%3Dc9da8d098&gsm=1&rpstart=0&rpnum=0&islist=&querylist=&force=undefined","2.jpg");
    	ThreadCallable t3 = new ThreadCallable("https://image.baidu.com/search/detail?ct=503316480&z=0&ipn=false&word=%E7%94%B5%E8%84%91%E5%A3%81%E7%BA%B8&step_word=&hs=0&pn=2&spn=0&di=156200&pi=0&rn=1&tn=baiduimagedetail&is=0%2C0&istype=0&ie=utf-8&oe=utf-8&in=&cl=2&lm=-1&st=undefined&cs=3883283873%2C2209997708&os=542829189%2C2419561689&simid=0%2C0&adpicid=0&lpn=0&ln=30&fr=&fmq=1601886433058_R&fm=&ic=undefined&s=undefined&hd=undefined&latest=undefined&copyright=undefined&se=&sme=&tab=0&width=undefined&height=undefined&face=undefined&ist=&jit=&cg=wallpaper&bdtype=0&oriquery=%E7%94%B5%E8%84%91%E5%A3%81%E7%BA%B8&objurl=http%3A%2F%2Fa4.att.hudong.com%2F05%2F50%2F300001069758129557502950786.jpg&fromurl=ippr_z2C%24qAzdH3FAzdH3Fooo_z%26e3Bzi5g2rjg2y7_z%26e3BvgAzdH3FpAzdH3Faaaabcbm8AzdH3F&gsm=1&rpstart=0&rpnum=0&islist=&querylist=&force=undefined","3.jpg");
    	
    	//创建执行服务
    	ExecutorService ser = Executors.newFixedThreadPool(3);
    	
    	//提交执行
    	Future<Boolean> r1 = ser.submit(t1);
    	Future<Boolean> r2 = ser.submit(t2);
    	Future<Boolean> r3 = ser.submit(t3);
    	
    	//获取结果
    	boolean rs1 = r1.get();
    	boolean rs2 = r2.get();
    	boolean rs3 = r3.get();
    	
    	//关闭服务
    	ser.shutdownNow();
    }
}

以上就是java实现多线程的三种方法。下面附加两个多线程的例子

//多个线程同时操作同一个对象
//买火车票的例子

//问题:多个线程同时操作一个资源的情况下,线程不安全,数据紊乱
public class testThread4 implements Runnable {
    
	//票数
	private int ticketNums = 10;
	
	@Override
	public void run() {
		// TODO Auto-generated method stub
		while(true) {
			if(ticketNums<=1) {
				break;
			}
			//模拟延时
			try {
				
				Thread.sleep(200);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			System.out.println(Thread.currentThread().getName()+"-->拿到了第"+ticketNums--+"票");
		}
	}
	
    public static void main(String[] args) {
    	
    	testThread4 ticket = new testThread4();
    	
    	new Thread(ticket,"小明").start();
    	new Thread(ticket,"老师").start();
    	new Thread(ticket,"黄牛").start();
    }
}
//模拟龟兔赛跑
public class Race implements Runnable {
    
	//胜利者
	private static String winner;
	
	@Override
	public void run() {
		// TODO Auto-generated method stub
		for(int i = 0; i <= 100; i++) {
			
			//模拟兔子休息
			if(Thread.currentThread().getName().equals("兔子")&& i%10 == 0) {
				try {
					Thread.sleep(20);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			//判断比赛是否结束
			boolean flag = gameOver(i);
			//如果结束,终结程序
			if(flag) {
				break;
			}
			System.out.println(Thread.currentThread().getName()+"-->跑了"+i+"步");
			
		}
	}
     
	//判断是否完成比赛
	private boolean gameOver(int steps) {
		//判断是否有胜利者
		if(winner != null) {
			//已经有胜利者
			return true;
		}else if(steps == 100){
			winner = Thread.currentThread().getName();
			System.out.println("winner is "+winner);
			return true;
		}
		return false;
	}
	
	public static void main(String[] args) {
		Race race = new Race();
		
		new Thread(race, "兔子").start();
		new Thread(race, "乌龟").start();
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值