首页 > 编程知识 正文

多线程的原理以及如何实现,java多线程方法

时间:2023-05-04 16:16:09 阅读:17423 作者:1225

前言: java多线程其实在工作中接触的并不多,所以偶尔会尝试一下。 但是,这个特性也是开发工程师走向wldbm时必须掌握的知识点,所以花了几天时间整理了一下。 一方面便于整理知识点,另一方面也有利于今后的易用性。

1 .线程和进程线程可以理解为是可以在一个程序中独立执行的模块。 多线程的最明显的特征是一个程序在一个时间段内同时做一些事情(至少表面上看起来是这样)。

过程是计算机的执行活动,可以是整个程序,也可以是部分程序的动态执行

概念上,进程包含线程,而一个进程至少包含一个线程。

区别:

1 .系统资源管理区分过程在操作系统上运行,有独立的地址空间; 线程在进程中运行,一个进程可以有多个线程。 可以在一个进程中交替切换多线程,从而提高系统的并发性。

2 .通信行为区分过程是通过操作系统传输指令,具有独立资源的单位; 线程没有系统资源,只能访问进程的资源; 同一进程的多个线程可以共享此进程的所有资源; 线程有自己的堆栈空间,并有独立的执行序列。

3 .在区分开销创建进程时,系统需要分配内存空间; 切换进程时,必须保存当前进程的CPU环境,并为计划运行的进程设置CPU环境。 创建线程不需要分配内存,即使在使用其所属的进程资源切换线程时,只要存储和设置少量寄存器的内容即可的线程所消耗的资源也远远小于进程,而与内存管理方面的操作无关。

二.线程生命周期1 .线程状态新建状态

可运转状态

运转状态

阻塞状态

结束状态

三、实现多线程的两种基础方法Thread重写run方法publicclassmythreadextendsthread { private intnum; 私有字符串读名称; 私密长结果; publicmythread(intnum,String threadName ) { this.threadName=threadName; this.num=num; }公共void run () ) for(intI=0; i num; I ) { result =i; } }公共字符串获取thread name () { return threadName; } publicvoidsetresult (long result ) { this.result=result; }公共长get result (() { return result; }2. publicclassmyrunnableimplementsrunnable { private intnum,用于实现runnable接口的run方法重写; 私有字符串读名称; 私密长结果; publicmyrunnable(intnum,String threadName ) { this.threadName=threadName; this.num=num; }公共void run () ) for(intI=0; i num; I ) { result =i; } }公共字符串获取thread name () { return threadName; } publicvoidsetresult (long result ) { this.result=result; }公共长get result (() { return result; }3.测试两种方法的打包路线; 公共类主{ publicstaticvoidmain (字符串[ ] args ) { threadTest ); //runnableTest (; }私有静态语音threadtest () mythreadmythread_1=newmythread ) 10,' thread_1' ); my thread my thread_2=new my thread (10000,' thread _2'; mythread_1.setresult(10; myThread_1.start (; myThread_2.start (; do { system.out.println----------------------------------------------------打印机------------------------------------------.----------------------------------------------

--"); System.out.println("thread name: " + myThread_1.getThreadName() + ", status: " + myThread_1.isAlive() + ",result: " + myThread_1.getResult()); System.out.println("thread name: " + myThread_2.getThreadName() + ", status: " + myThread_2.isAlive() + ",result: " + myThread_2.getResult()); } while (myThread_1.isAlive() || myThread_2.isAlive()); } private static void runnableTest() { MyRunnable myRunnable_1 = new MyRunnable(10, "runnable_1"); MyRunnable myRunnable_2 = new MyRunnable(10000, "runnable_2"); Thread thread_1 = new Thread(myRunnable_1); Thread thread_2 = new Thread(myRunnable_2); thread_1.start(); thread_2.start(); do { System.out.println("--------------------------------------------------"); System.out.println("thread name: " + myRunnable_1.getThreadName() + ", status: " + thread_1.isAlive() + ",result: " + myRunnable_1.getResult()); System.out.println("thread name: " + myRunnable_2.getThreadName() + ", status: " + thread_2.isAlive() + ",result: " + myRunnable_2.getResult()); } while (thread_1.isAlive() || thread_2.isAlive()); }} 4. 两种方法的比较

如果非要说区别,其实就是实现接口和继承的区别,看开发者的使用习惯

另外一点,两种方法的run都是不能传参数的,只能通过类的方法设置参数使用

四、实现Callable接口重写call()方法实现多线程

上述两种基础方法的run都是void类型,想获取返回只能另加逻辑,而实现Callable接口重写call()方法的好处是允许call函数有返回,下面举例

import java.util.concurrent.Callable;public class MyCall implements Callable<Long> { private int num; private String threadName; private long result; public MyCall(int num, String threadName) { this.threadName = threadName; this.num = num; } public Long call() throws Exception { for (int i = 0; i < num; i++) { result += i; } return result; }}// 下面是测试import java.util.concurrent.ExecutionException;import java.util.concurrent.FutureTask;public class Main { public static void main(String[] args) { try { callTest(); } catch (ExecutionException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } } private static void callTest() throws ExecutionException, InterruptedException { MyCall myCall_1 = new MyCall(10, "call_1"); MyCall myCall_2 = new MyCall(10000, "call_2"); FutureTask<Long> f1 = new FutureTask<Long>(myCall_1); FutureTask<Long> f2 = new FutureTask<Long>(myCall_2); Thread thread_1 = new Thread(f1); Thread thread_2 = new Thread(f2); thread_1.start(); thread_2.start(); System.out.println(f1.get()); // 获取返回 System.out.println(f2.get()); // 获取返回 }} 五、线程池管理多线程

给一个简单的样例

import java.util.concurrent.Callable;public class MyCall implements Callable<Long> { private int num; private String threadName; private long result; public MyCall(int num, String threadName) { this.threadName = threadName; this.num = num; } public Long call() throws Exception { for (int i = 0; i < num; i++) { result += i; } return result; }}// 线程池方式测试import java.util.concurrent.ExecutionException;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.Future;public class ThreadPool { public static void main(String[] args) throws ExecutionException, InterruptedException { MyCall myCall_1 = new MyCall(10, "call_1"); MyCall myCall_2 = new MyCall(10000, "call_2"); ExecutorService service = Executors.newFixedThreadPool(5); Future<Long> f1 = service.submit(myCall_1); Future<Long> f2 = service.submit(myCall_2); System.out.println(f1.get()); // 获取返回 System.out.println(f2.get()); // 获取返回 service.shutdown(); }} 六、四种方式总结

1. 继承Thread和实现Runnable使用起来比较接近,唯一区别就是Runnable避免了单一继承的缺点

2. 有返回的情况下建议使用Callable,而且可以抛出异常方便定位问题

3.线程池其实不算是实现方式(有些人会把这个也算是实现方式),它更像是一种管理多线程的方式

 

 

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。