- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章java实现/创建线程的几种方式小结由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
进程可以简单理解成一个可执行程序例如.exe,在Windows中的任务管理器中可以查看每一个进程,进程是一次程序的执行,是程序在数据集合上运行的过程,是系统资源调度的一个单位。进程主要负责向操作系统申请资源。然而一个进程中,多个线程可以共享进程中相同的内存或文件资源。线程就是一个进程一个程序要完成所依赖的子任务,这些子任务便可以看作是一个线程.
从java源码可以看出Thread类本质上实现了Runnable接口的实例类,代表了线程的一个线程的实例,启动的线程唯一办法就是通过Thread类调用start()方法,start()方法是需要本地操作系统的支持,它将启动一个新的线程,并且执行run()方法.
继承Thread类实现线程代码如下 。
创建一个Thread类,对象直接调用run方法会出现什么问题?
package cn.thread.线程;public class MyThread extends Thread{ public MyThread(String name){ super(null,null,name); } int piao =10; @Override public void run() { while(piao>0){ System.out.println(Thread.currentThread().getName()+"......"+piao--); } } public static void main(String[] args) { MyThread mt = new MyThread("x"); mt.run(); }}
结果:
可以发现是主线程执行了run方法,并不是用户线程执行的run方法,此时可以得出用户线程并没有启动,所以并不会执行run里面的方法,且执行完run方法便结束线程.
相比继承Thread类而言,实现接口的可扩展性得到了提升,Runnable接口也必须要封装到Thread类里面,才可以调用start方法,启动线程.
实现代码 。
package cn.thread.线程;public class MyRunnable implements Runnable{ int piao = 10; @Override public void run() { while(piao>0){ System.out.println(Thread.currentThread().getName()+"-----"+piao--); } } public static void main(String[] args) { Runnable r =new MyRunnable(); Thread t =new Thread(r); t.start(); }}
结果 。
Callable接口使用方法和Runnable接口的方法类似不同的一点是Callable接口具有返回值,返回结果并且可能抛出异常的任务。实现者定义了一个不带任何参数的叫做 call 的方法。 Callable 接口类似于 Runnable,两者都是为那些其实例可能被另一个线程执行的类设计的。但是 Runnable 不会返回结果,并且无法抛出经过检查的异常.
实现代码 。
对下列代码进行分析 。
首先callable是接口不能直接创建对象,也不能创建线程。并且要实现call方法类似run方法的功能,call方法有返回值,会计算结果,如果无法计算结果,则抛出一个异常.
执行callable任务之后,可以获得一个future的对象,future基本上是主线程可以跟踪进度以及获取其他线程结果的一种方式。在这里Test1()方法主要利用线程池和future的方法,去启动实现Callable接口的线程,具有返回值。而Test2()主要是采用FutureTask类去实现创建一个实现callable接口的线程,futuretask实现了future接口.
package com.openlab.test;import java.util.Random;import java.util.concurrent.Callable;public class CallableTest implements Callable{ @Override public Object call() throws Exception { Random generator = new Random(); Integer randomNumber = generator.nextInt(5); Thread.sleep(randomNumber*1000); return randomNumber; }}
综合练习代码:
package cn.thread.线程;import java.util.ArrayList;import java.util.Date;import java.util.List;import java.util.Random;import java.util.concurrent.*;public class CallableTest implements Callable<Object> {//不能直接创建线程 int taskNum; public CallableTest(int taskNum){ this.taskNum = taskNum; } @Override public Object call() throws Exception { System.out.println(">>>"+taskNum+"任务启动"); Date dataTemp = new Date(); Thread.sleep(1000); Date dataTemp2 = new Date(); long time = dataTemp2.getTime() - dataTemp.getTime(); System.out.println(">>>>"+taskNum+"任务终止"); return taskNum+"任务返回运行结果"+time;// Random generator = new Random();// Integer randomNumber = generator.nextInt(5);// Thread.sleep(randomNumber*1000);// return randomNumber; } /*test1方法采用Executors的静态方法newFixedThreadPool(taskSize) 创建一个可重用固定线程集合的 线程池,以共享的无界队列方式来运行这些线程,获取线程池。ExecutorService的submit方法提交一个 callable实例,得到一个future对象,最终将future对象存储在list数组中,加入线程池的过程中就代表 着线程已经开始执行,相当于一个线程池代理过程,就不需要采用start方法启动线程。最后对future进行 打印输出。切记一定要关闭线程池!*/ static void test1() throws ExecutionException, InterruptedException { System.out.println("程序开始"); Date data1 = new Date(); int taskSize = 5; //构建线程池对象 ExecutorService pool = Executors.newFixedThreadPool(taskSize); List<Future> list =new ArrayList<Future>(); for(int i=0;i<taskSize;i++){ Callable c = new CallableTest(i); Future f = pool.submit(c); list.add(pool.submit(c)); } //关闭线程池 pool.shutdown(); for(Future f:list){ System.out.println(">>>"+f.get().toString()); } Date date2 = new Date(); System.out.println("程序运行结束-----"+(date2.getTime()-data1.getTime())+"毫秒"); } /*test2方法主要是采用futuretask类,可以直接把callable作为参数来申明futuretask对象, 这里相当于把线程池换成了futuretask数组,因为test1线程池可以对callable进行封装, 在这里可以直接采用futuretask就行封装,在加上futuretask又实现了runnable接口, 所以可以直接创建线程采用start的方式进行启动线程。*/ static void test2() throws ExecutionException, InterruptedException { System.out.println("----程序开始-----"); Date date1 =new Date(); int taskSize = 5; FutureTask[] randNumber = new FutureTask[taskSize]; List<Future> list =new ArrayList<Future>(); for(int i=0;i<taskSize;i++){ Callable c = new CallableTest(i); randNumber[i] = new FutureTask(c); Thread t = new Thread(randNumber[i]); t.start(); } for(Future f:randNumber){ System.out.println(">>>"+f.get().toString()); } Date date2 = new Date(); System.out.println("程序运行结束-----"+(date2.getTime()-date1.getTime())+"毫秒"); } public static void main(String[] args) throws Exception {// CallableTest c = new CallableTest();// Integer i = (Integer) c.call(); test1(); test2(); }}
执行结果 。
其实在第三种的方法中就提到了两种实现方法,一种线程池+future,另一种futuretask的方法。线程和数据库连接这些资源都是非常宝贵的资源。那么每次需要的时候创建,不需要的时候销毁,是非常浪费资源的。那么我们就可以使用缓存的策略,也就是使用线程池.
// 创建线程池 ExecutorService threadPool = Executors.newFixedThreadPool(10); while(true) { threadPool.execute(new Runnable() { // 提交多个线程任务,并执行 @Override public void run() { System.out.println(Thread.currentThread().getName() + " is running .."); try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } } }); } }
理论上实现线程的方法还有一些,本文所提及到的,基本都是一些创建线程常用的方法。希望本文对大家在学习线程的过程中有所帮助.
原文链接:https://blog.csdn.net/cout_s/article/details/119452329 。
最后此篇关于java实现/创建线程的几种方式小结的文章就讲到这里了,如果你想了解更多关于java实现/创建线程的几种方式小结的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我一直在阅读有关汇编函数的内容,但对于是使用进入和退出还是仅使用调用/返回指令来快速执行,我感到很困惑。一种方式快而另一种方式更小吗?例如,在不内联函数的情况下,在汇编中执行此操作的最快(stdcal
我正在处理一个元组列表,如下所示: res = [('stori', 'JJ'), ('man', 'NN'), ('unnatur', 'JJ'), ('feel', 'NN'), ('pig',
最近我一直在做很多网络或 IO 绑定(bind)操作,使用线程有助于加快代码速度。我注意到我一直在一遍又一遍地编写这样的代码: threads = [] for machine, user, data
假设我有一个名为 user_stats 的资源,其中包含用户拥有的帖子、评论、喜欢和关注者的数量。是否有一种 RESTful 方式只询问该统计数据的一部分(即,对于 user_stats/3,请告诉我
我有一个简单的 api,它的工作原理是这样的: 用户创建一个请求 ( POST /requests ) 另一个用户检索所有请求 ( GET /requests ) 然后向请求添加报价 ( POST /
考虑以下 CDK Python 中的示例(对于这个问题,不需要 AWS 知识,这应该对基本上任何构建器模式都有效,我只是在这个示例中使用 CDK,因为我使用这个库遇到了这个问题。): from aws
Scala 中管理对象池的首选方法是什么? 我需要单线程创建和删除大规模对象(不需要同步)。在 C++ 中,我使用了静态对象数组。 在 Scala 中处理它的惯用和有效方法是什么? 最佳答案 我会把它
我有一个带有一些内置方法的类。这是该类的抽象示例: class Foo: def __init__(self): self.a = 0 self.b = 0
返回和检查方法执行的 Pythonic 方式 我目前在 python 代码中使用 golang 编码风格,决定移动 pythonic 方式 例子: import sys from typing imp
我正在开发一个 RESTful API。其中一个 URL 允许调用者通过 id 请求特定人员的记录。 返回该 id 不存在的记录的常规值是什么?服务器是否应该发回一个空对象或者一个 404,或者其他什
我正在使用 pathlib.Path() 检查文件是否存在,并使用 rasterio 将其作为图像打开. filename = pathlib.Path("./my_file-name.tif") 但
我正在寻找一种 Pythonic 方式来从列表和字典创建嵌套字典。以下两个语句产生相同的结果: a = [3, 4] b = {'a': 1, 'b': 2} c = dict(zip(b, a))
我有一个正在操裁剪理设备的脚本。设备有时会发生物理故障,当它发生时,我想重置设备并继续执行脚本。我有这个: while True: do_device_control() device
做组合别名的最pythonic和正确的方法是什么? 这是一个假设的场景: class House: def cleanup(self, arg1, arg2, kwarg1=False):
我正在开发一个小型客户端服务器程序来收集订单。我想以“REST(ful)方式”来做到这一点。 我想做的是: 收集所有订单行(产品和数量)并将完整订单发送到服务器 目前我看到有两种选择: 将每个订单行发
我知道在 Groovy 中您可以使用字符串调用类/对象上的方法。例如: Foo."get"(1) /* or */ String meth = "get" Foo."$meth"(1) 有没有办法
在 ECMAScript6 中,您可以使用扩展运算符来解构这样的对象 const {a, ...rest} = obj; 它将 obj 浅拷贝到 rest,不带属性 a。 有没有一种干净的方法可以在
我有几个函数返回数字或None。我希望我的包装函数返回第一个不是 None 的结果。除了下面的方法之外,还有其他方法吗? def func1(): return None def func2(
假设我想设计一个 REST api 来讨论歌曲、专辑和艺术家(实际上我就是这样做的,就像我之前的 1312414 个人一样)。 歌曲资源始终与其所属专辑相关联。相反,专辑资源与其包含的所有歌曲相关联。
这是我认为必须经常出现的问题,但我一直无法找到一个好的解决方案。假设我有一个函数,它可以作为参数传递一个开放资源(如文件或数据库连接对象),或者需要自己创建一个。如果函数需要自己打开文件,最佳实践通常
我是一名优秀的程序员,十分优秀!