Java实现线程的方式

文章详细介绍了线程和进程的概念,包括线程作为进程内部的执行任务,它们之间的资源分配差异,以及进程作为资源分配的最小单元。线程的创建方法包括继承Thread类、实现Runnable接口和Callable接口,以及使用线程池。文章还提到了线程的生命周期,包括NEW、RUNNABLE、BLOCKED、WAITING、TIMED_WAITING和TERMINATED六种状态。
摘要由CSDN通过智能技术生成
一、线程:进程内部按顺序执行的任务,多个线程之间可以同时执行。线程共享进程的资源,但是线程之间不能共享资源,每个线程内部有自己的程序计数器。一个进程包含多个线程,至少存在一个主线程。

二、进程和线程的区别

1、进程是操作系统分配资源的最小单元;而线程是操作系统最小的执行单元。

2、进程中的线程共享其进程的资源和内存空间;而线程之间不能共享资源和内存空间。

3、进程可以独立执行;而线程必须依赖其进程才能执行。

4、一个进程中包含多个线程,这些线程之间可以同时进行执行。

5、进程资源开销大,而线程资源开销小。

三、线程的创建

总的来说,创建线程只有一种方法就是创建Thread对象,别的方法是从代码实现角度对其进行划分的,其内部代码实现终归还是在创建Thread对象。

1.创建一个Thread对象

        //创建子线程1(继承Thread类)
		
		System.out.println("主线程执行开始........");
		//创建Thread对象,实现匿名类(该类不能被复用)   
		Thread t1 = new Thread("线程1") {
			//重写run方法
			@Override
			public void run() {
				for(int i=1;i<=100;i++) {
					System.out.println("[线程1]:"+i);
				}
			}
		};
		//启动线程
		t1.start();
		
		//创建子线程2
		//创建Thread对象,实现匿名类
		Thread t2 = new Thread("线程2") {
			@Override
			public void run() {
				for(char c='A';c<='x';c++) {
					System.out.println("[线程2]:"+c);
				}
			}
		};
		//启动线程
		t2.start();
		System.out.println("主线程执行结束........");

2.创建线程的方式1:继承Thread类(不会返回执行结果)

public class Demo02 {
	public static void main(String[] args) {
		//创建SubThread对象,传入线程的名称
		SubThread t1 = new SubThread("线程甲");
		SubThread t2 = new SubThread("线程乙");
		SubThread t3 = new SubThread("线程丙");
		
		//启动线程
		t1.start();
		t2.start();
		t3.start();
	}
}

//继承Tread类
class SubThread extends Thread{
	
	public SubThread(String name) {
		//调父类的构造方法,传入name
		super(name);
	}
	//重写Tread类的run()方法
	@Override
	public void run() {
		//循环输出大写字母
		for(char c = 'A';c<='Z';c++) {
			System.out.println(this.getName()+":"+c);
		}
	}
}

3、创建线程的方式2:实现Runnable接口(不会返回执行结果)

public class Demo03 {
	public static void main(String[] args) {
		//每个Runnable接口的实现类,封装了线程执行逻辑
		EmailTask emailTask = new EmailTask();
		
		//创建线程对象,传入"线程执行逻辑"和线程"名称",分别发送邮件
		Thread t1 = new Thread(emailTask,"线程T1");
		Thread t2 = new Thread(emailTask,"线程T2");
		Thread t3 = new Thread(emailTask,"线程T3");
		
		//启动线程
		t1.start();
		t2.start();
		t3.start();
	}
}

//子类(邮件任务)
//继承Task类,实现Runnable接口
class EmailTask extends Task implements Runnable{
	//重写父类的方法(线程的执行)
	@Override
	public void execute() {
		//获取当前线程对象
		Thread thread = Thread.currentThread();
		//获取线程名称
		String threadName = thread.getName();
		//模拟线程的执行逻辑
		System.out.println(threadName + ":使用JavaMail技术,通过smtp协议发送邮件");
	}
	//因为Runnable接口实现了Thread类
	@Override
	public void run() {
		execute();
	}
	
}

//父类(任务)
abstract class Task{
	public abstract void execute();
}

4、创建线程的方式3:实现Callable接口(泛型方法)

因为Thread对象的参数不接收Callable对象,所以要定义一个既可以接收Callable对象的,又可以被Thread对象接收的对象------->FutureTask对象。FutureTask调用时会调用run方法,而FutureTask类中又定义的有Callable对象,所以会调用call()方法。

public class Demo04 {
	public static void main(String[] args) throws InterruptedException, ExecutionException {
		//Callable接口的实现类:不同数据范围的计算任务
		SumCalu sumCalu1 = new SumCalu(1,300);//1-300
		SumCalu sumCalu2 = new SumCalu(301,500);//301-500
		SumCalu sumCalu3 = new SumCalu(501,1000);//501-1000
		
		//FutureTask类间接也是Callable的实现类
		FutureTask<Integer> futureTask1 = new FutureTask<Integer>(sumCalu1);
		FutureTask<Integer> futureTask2 = new FutureTask<Integer>(sumCalu2);
		FutureTask<Integer> futureTask3 = new FutureTask<Integer>(sumCalu3);
		
		//创建线程对象,传入
		Thread t1 = new Thread(futureTask1);
		Thread t2 = new Thread(futureTask2);
		Thread t3 = new Thread(futureTask3);
		
		//启动线程
		t1.start();
		t2.start();
		t3.start();
		
		//线程执行结束,分别获取各自线程的返回结果
		System.out.println("开始分别获取......");
		Integer sum1 = futureTask1.get();
		Integer sum2 = futureTask2.get();
		Integer sum3 = futureTask3.get();
		
		//汇总结果
		System.out.println("汇总各自计算结果");
		Integer sum = sum1+sum2+sum3;
		System.out.println("汇总结果:"+sum);
	}
}

//通过Callable接口实现类SumCalu封装某个范围内数据的累加和
class SumCalu implements Callable<Integer>{

	private int begin,end;
	//有参构造方法
	public SumCalu(int begin,int end) {
		this.begin = begin;
		this.end = begin;
	}
	
	//执行逻辑
	@Override
	public Integer call() throws Exception {
		int total = 0;
		for(int i=begin;i<=end;i++) {
			total += i;
		}
		//获取当前线程的名称
		System.out.println(Thread.currentThread().getName());
		return total;
	}
	
}

5、创建线程的方式4:通过线程池创建

执行线程任务有两种方式:executer()和submit()。execute()只能提交Runnable类型的任务,且没有返回结果;submit()既能提交Runnable类型的任务,又能提交Callable类型的任务,且可以返回Future类型的结果。

public class Demo05 {
	public static void main(String[] args) {
		//创建固定数量(10)的线程池
		ExecutorService executorService =  Executors.newFixedThreadPool(10);
		
		//不确定数量的线程池请求
		while(true) {
			//向线程池提交一个执行任务(Runnable接口实现类对象)
			//线程池分配一个"空闲线程"执行该任务
			//如果没有空闲线程,则该任务进入"等待队列(工作队列)"
			executorService.execute(new Runnable() {
				@Override
				public void run() {
					System.out.println(Thread.currentThread().getName()+"进行了一次投票!");
					try {
						//当前线程休眠1000毫秒
						Thread.sleep(1000);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			});
		}
	}
}

 四、线程生命周期的六种状态

1、NEW:新建状态,线程刚创建,还没有调用start()方法。

2、RUNNABLE:运行状态,调用了start()方法,线程即将执行或正在执行run()方法。

3、BLOCKED:阻塞状态,线程在竞争锁时,没有竞争到锁,被阻塞。

4、WATING:等待状态,调用sleep(),join()等方法。

5、Timed Wating:计时等待状态,调用sleep(毫秒值),join(毫秒值)等方法。

6、Terminated:终止状态,执行完run()方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值