Java实现多线程的四种方式

前言:

今天给大家分享的java多线程的实现方式,估计一堆人,早已掌握,在这里也是再做一次回忆,加深一下印象。在上代码之前,我觉得不如分享下我是怎么学习多线程的。因为菜鸟一号表示当初学习的时候就被进程和线程搞得很烦。很烦咋办呢,我就先问度娘,她是这么说的
进程的定义
老实说,菜鸟就没看懂,越看越懵。看来度娘也不是万能的。那咋办呢,不急不急,动起你那勤快的小手,ctrl+alt+. 然后跳出这么个东西
任务服务管理器
看到哪个红色框框木有?

难道你是想说系统运行的exe程序,就能代表一个线程?没错!
通过查看任务服务管理器,我们可以将运行在内存中的exe文件,如图中的erl.exe文件理解成进程。而进程是受操作系统管理的基本运行单元。看到这里,是不是觉得,有点顿悟的感觉。

那么线程又是什么妖魔鬼怪呢?这玩意就很好理解了,当你打开英雄联盟.exe时他就有很多子任务也在同时运行,如开黑的语音线程,聊天窗口的线程,背景音乐线程,last but not least (放个洋屁)你正在操作的英雄的界面也是一个线程,这些不同的任务,或者说是功能都可以同时运行,其中每一项任务都可以理解为线程在工作,传输文件,发送消息。每一个功能都有对应的线程在后台默默执行。而多个线程同时工作,也就形成的多线程。就像你打撸啊撸时,就是多线程工作的完美体现。

多线程的特显就是在同一时间内可以执行多个任务,当然这也是多线程的优点。使用多线程其实就是在使用异步。

那么什么场景下需要使用多线程呢?

  1. 系统阻塞时。一旦系统阻塞,单线程就相当于宕机,我们需要使用多线程技术来提高运行效率。
  2. 当一个业务需要分两步A、B去完成时,如果A阻塞,B的执行不需要依赖于A的执行结果。那就可以使用多线程技术,提高运行效率。
    注意!实际开发需要根据业务需求来确定使用单线程还是多线程,并不是说多线程就一定好于单线程。

我淦!晚上11点了,今天先分享这么多,下次分享多线程实现的几种方式!
----------------------------------------------2021/1/9 22点55分(sun)。
Thread类的方法

实现多线程的四个方式:(这里分享的都是多线程同步的案例)
1.继承Thread类然后重写run()方法;

public class MyThread extends Thread{
	private int ticket = 5;
	@Override
	synchronized public void run() {
		super.run();
		ticket--;
		System.out.println("当前线程"+this.currentThread().getName()+"操作"+ ticket);		
	}
}


public class Test {

	public static void main(String[] args) {
		MyThread myThread = new MyThread();
		Thread t1 =new Thread(myThread,"A");
		Thread t2 =new Thread(myThread,"B");
		Thread t3 =new Thread(myThread,"C");
		Thread t4 =new Thread(myThread,"D");
		Thread t5 =new Thread(myThread,"E");
		t1.start();//耗时
		t2.start();
		t3.start();
		t4.start();
		t5.start();
	}
}

运行结果
这是线程安全的案例,必须要使用synchronized关键字去保证线程安全,如果不加就会产生线程安全问题。
这里我列出不加上synchronized关键字运行的结果:
在这里插入图片描述
显然线程A和B输出的都是3,说明它两对3同时进行处理,就产生了线程安全问题。
2.实现Runnable接口重写Run()方法。

package com.sun.thread;
public class MyThreadRun implements Runnable{
	private int ticket = 5;
	@Override
	synchronized public void run() {
			ticket--;
			System.out.println(Thread.currentThread().getName()+" "+ticket);
	}
}

package com.sun.test;

import com.sun.thread.MyThreadRun;

public class TestRunable {
	public static void main(String[] args) {
		MyThreadRun myThreadRun = new MyThreadRun();
		Thread t1= new Thread(myThreadRun);
		Thread t2= new Thread(myThreadRun);
		Thread t3= new Thread(myThreadRun);
		Thread t4= new Thread(myThreadRun);
		Thread t5= new Thread(myThreadRun);
		t1.start();
		t2.start();
		t3.start();
		t4.start();
		t5.start();	
	}
}

在这里插入图片描述
3.实现callable接口重写run方法:它有返回值,runnable没有。

package com.sun.thread;

import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
/**
 * Runnable接口:重写run() run()方法里面写的是线程执行的业务逻辑。
 * 				run()方法没有返回值,无法获取到线程执行的结果。
 * Callable接口:重写call() call()方法里面写的也是线程执行的业务逻辑。
 * 				call()方法有返回值,可以获取到每个线程执行的结果。
 * @author Administrator
 *<P>Title:MyThreadCall</p>
 *<P>Description: </p>
 * @author svv
 */
public class MyThreadCall implements Callable<String>{

	@Override
	public String call() throws Exception {
		System.out.println("我执行了"+Thread.currentThread().getName());
		return "ZXZXZX";
	}
	public static void main(String[] args) throws Exception {
		Callable<String> callable = new MyThreadCall();
		//FutureTask对象是用来接受异步执行的结果
		FutureTask<String> futureTask1 = new FutureTask<>(callable);
		FutureTask<String> futureTask2 = new FutureTask<>(callable);
		FutureTask<String> futureTask3 = new FutureTask<>(callable);
		FutureTask<String> futureTask4 = new FutureTask<>(callable);
		Thread thread = new Thread(futureTask1);
		Thread thread1 = new Thread(futureTask2);
		Thread thread2 = new Thread(futureTask3);
		Thread thread3 = new Thread(futureTask4);
		thread.start();
		thread1.start();
		thread2.start();
		thread3.start();
		System.out.println(futureTask1.get());
		System.out.println(futureTask1.get());
		System.out.println(futureTask1.get());
		System.out.println(futureTask1.get());
	}
}

在这里插入图片描述
4.基于Callable接口,利用Java的线程池来实现多线程.。推荐,好处就是多路复用(高效利用每一线程,提高线程的利用率。应用程序的执行效率和速度也随之提高。)

package com.sun.thread;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class ThreadPool implements Callable<String>{

	@Override
	public String call() throws Exception {
		return "当前线程"+Thread.currentThread().getName();
	}
	public static void main(String[] args) throws Exception{
		//创建初始化线程池
		ExecutorService executorService = Executors.newFixedThreadPool(5);
		for(int i = 0;i<10;i++){
			//创建资源访问对象
			ThreadPool threadPool = new ThreadPool();
			//提交资源任务
			Future<String> submit = executorService.submit(threadPool);
			System.out.println(submit.get());
		}
		//关闭线程池
		executorService.shutdown();
	}
}

在这里插入图片描述
Executors类:提供了一系列工厂方法用于创建线程池,返回的线程池都实现了ExecutorService接口。

  1. public static ExecutorService newFixedThreadPool(int nThreads)
    创建固定数目线程的线程池。
  2. public static ExecutorService newCachedThreadPool()
    创建一个可缓存的线程池,调用execute 将重用以前构造的线程(如果线程可用)。如果现有线程没有可用的,则创建一个新线程并添加到池中。终止并从缓存中移除那些已有 60 秒钟未被使用的线程。
    3.public static ExecutorService newSingleThreadExecutor()
    创建一个单线程化的Executor。
  3. public static ScheduledExecutorService
    newScheduledThreadPool(int corePoolSize)
    创建一个支持定时及周期性的任务执行的线程池,多数情况下可用来替代Timer类。
    ExecutoreService提供了submit()方法,传递一个Callable,或Runnable,返回Future。如果Executor后台线程池还没有完成Callable的计算,这调用返回Future对象的get()方法,会阻塞直到计算完成。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值