command对象提供的3个execute方法是_并发面试题:java中有几种方法可以实现一个线程?...

创建并启动线程的6种方式

  • 继承Thread类创建线程
  • 实现Runnable接口创建线程
  • 使用Callable和FutureTask创建线程
  • 使用线程池,例如用Executor框架
  • Spring实现多线程(底层是线程池)
  • 定时器Timer (底层封装了一个TimerThread对象)

1、继承Thread类创建线程

1.1继承Thread类方式创建线程的实现步骤:

步骤:

1) 定义一个类A继承于java.lang.Thread类

2)在A类中覆盖Thread类中的run方法

3)我们在run方法中编写需要执行的操作---->run方法里的,线程执行体

4)在main方法(线程)中,创建线程对象,并启动线程

  • 创建线程类对象: A类 a = new A类();
  • 调用线程对象的start方法: a.start();//启动一个线程

注意:千万不要调用run方法,如果调用run方法好比是对象调用方法,依然还是只有一个线程,并没有开启新的线程。

1.2需求:使用两个线程实现边听歌边打游戏

实现代码:

//音乐线程
public class MusicThread {
public static void main(String[] args) {
//创建游戏线程对象
GameThread game = new GameThread();
//启动游戏线程
game.start();
while(true){
System.out.println(Thread.currentThread().getName()+"听音乐!");
}
}
}
//游戏线程
class GameThread extends Thread{
@Override
public void run() {
while (true) {
System.out.println(Thread.currentThread().getName()+"打游戏!");
}
}
}

注意:有的小伙伴可能觉得音乐线程没有启动,在这里其实音乐线程已经启动起来了,而启动音乐线程的对象就是我们的JVM,此处main方法其实启动的时候会创建一个主线程去执行main方法,所以我在这里使用主线程作为了我的音乐线程。

2、实现Runnable接口创建线程

2.1实现Runnable接口方式创建线程的实现步骤:

1)定义一个类A实现于java.lang.Runnable接口,注意A类不是线程类。 2)在A类中覆盖Runnable接口中的run方法。 3) 我们在run方法中编写需要执行的操作---->run方法里的,线程执行体。 4)在main方法(线程)中,创建线程对象,并启动线程。

  • 创建线程类对象: Thread t = new Thread(new A());
  • 调用线程对象的start方法: t.start();

2.2需求:使用两个线程实现边听歌边打游戏

实现代码:

//音乐线程
public class MusicThread {
public static void main(String[] args) {
//创建游戏线程对象
Thread game = new Thread(new Game());
//启动游戏线程
game.start();
while(true){
System.out.println(Thread.currentThread().getName()+"听音乐!");
}
}
}//游戏
class Game implements Runnable{
@Override
public void run() {
while (true) {
System.out.println(Thread.currentThread().getName()+"打游戏!");
}
}
}

2.3 继承方式和实现方式的区别

1)继承方式是一个类继承了Thread后成为线程类的子类,实现方式是一个类实现Runnable接口,但是这个类不是线程类,因为该类没有start等方法。

2)启动的时候继承方式直接调用自己的start方法,实现方式是借助了Thread中的start方法启动的,自身没有start方法。

3)继承方式调用的run方法是通过方法覆盖,通过继承方式实现的,运行的时候先找子类,没有最后才运行父类的run方法。实现方式是执行Thread的run方法,而Thread中的run方法调用了实现类中的run方法,使用过组合关系的方法调用实现的。

3、实现 Callable 接口

3.1使用Callable和FutureTask创建线程的实现步骤:

1)定义一个Callable接口的实现类

2)创建Callable实现类对象传递给FutureTask构造器

3)将FutureTask对象传递给Thread构造器

4)Thread对象调用start方法启动线程

5)通过FutureTask对象的get方法获取线程运行的结果

注意: Future就是对于具体的Runnable或者Callable任务的执行结果进行取消、查询是否完成、获取结果。必要时可以通过get方法获取执行结果,该方法会阻塞直到任务返回结果。

使用场景:使用多线程计算结果并返回该结果。

3.2需求:使用2个线程异步计算1-1000,000内之和

实现代码:

public class CallableDemo {
public static void main(String[] args) throws Exception  {
//1.创建并启动线程
Callable<Integer> call1 = new CallableImpl(0, 50000);
Callable<Integer> call2 = new CallableImpl(50001, 100000);FutureTask<Integer> f1 = new FutureTask<>(call1);
FutureTask<Integer> f2 = new FutureTask<>(call2);new Thread(f1).start();
new Thread(f2).start();
//2.获取每一个线程的结果
int ret1 = f1.get();
int ret2 = f2.get();
int ret= ret1+ret2;
System.out.println(ret);
}
}
class CallableImpl implements Callable<Integer>{private int min;
private int max;public CallableImpl(int min, int max) {
this.min = min;
this.max = max;
}@Override
public Integer call() throws Exception {
int sum = 0;
for (int i = min; i <= max; i++) {
sum+=i;
}
return sum;
}
}

3.3Callable和Runnable的区别如下:

Callable定义的方法是call,而Runnable定义的方法是run。

Callable的call方法可以有返回值,而Runnable的run方法不能有返回值。

Callable的call方法可抛出异常,而Runnable的run方法不能抛出异常。

注意:

FutureTask为Runnable的实现类

FutureTask可以视为一个闭锁(门闩),因为只有当线程运行完才会出现结果。

4、使用线程池

线程池,顾名思义就是一个池子里面放了很多的线程,我们用就将线程从里面拿出来,使用完毕就放回去池子中。设计和数据库连接池相似,存在静态工厂方法用于创建各种线程池。

操作步骤:

1)使用Executors工具类中的静态工厂方法用于创建线程池 newFixedThreadPool:创建可重用且固定线程数的线程池, newScheduledThreadPool:创建一个可延迟执行或定期执行的线程池 newCachedThreadPool:创建可缓存的线程池

2)使用execute方法启动线程

3)使用shutdown方法等待提交的任务执行完成并后关闭线程。

代码演示如下:

public class Demo4 {public static void main(String[] args) {Executor executor = Executors.newFixedThreadPool(5);executor.execute(new Runnable() {@Overridepublic void run() {System.out.println(Thread.currentThread().getName());}});((ExecutorService) executor).shutdown();}
}

5、Spring实现多线程

在Spring3之后,Spring引入了对多线程的支持,如果你使用的版本在3.1以前,应该还是需要通过传统的方式来实现多线程的。从Spring3同时也是新增了Java的配置方式,而且Java配置方式也逐渐成为主流的Spring的配置方式。

代码演示如下:

导入的包:

<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId><version>2.1.0.RELEASE</version></dependency>
</dependencies>

配置类:

@Configuration
@ComponentScan("cn.wolfcode")
@EnableAsync //允许使用异步任务
public class SpringConfig {}

服务类:

@Service
public class SpringService {@Async // 这里进行标注为异步任务,在执行此方法的时候,会单独开启线程来执行public void dowork1() {for (int i = 0; i < 10; i++) {System.out.println(Thread.currentThread().getName() + "-->" + i);}}@Asyncpublic void dowork2() {for (int i = 0; i < 10; i++) {System.out.println(Thread.currentThread().getName() + "-->" + i);}}
}

测试类:

public class SpringThreadDemo {public static void main(String[] args) {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);SpringService bean = context.getBean(SpringService.class);bean.dowork1();bean.dowork2();}
}

注意:此时会出现一个DEBUG信息

undefined_b.jpg

在这里DEBUG信息不是什么错误,不会影响代码的正常运行,其实可以不用管的,但是为什么出现这个问题呢?

Spring的定时任务调度器会通过BeanFactory.getBean的方法来尝试获取一个注册过的TaskExecutor对象来做任务调度,获取不到TaskExecutor对象再尝试找ScheduledExecutorService 对象,都找不到就报DEBUG信息。报错之后就找自己本身默认的scheduler定时器对象,这个举动其实是做一个提醒作用,所以如果没有强迫症可以不用管它。

解决Spring使用多线程的报错信息

强迫症患者想要解决怎么办,三种方式:

  • 在log4j文件中加入log4j.logger.org.springframework.scheduling = INFO(治标不治本)
  • 在本配置文件或者配置类中设置一个bean
  • 配置类实现AsyncConfigurer接口并覆盖其getAsyncExecutor方法

6 定时器

严格来说定时器(Timer)不是线程,他只是调度线程的一种工具,它里面封装了一个线程,所以我们可以使用定时器来使用线程。

undefined_b.jpg

undefined_b.jpg

操作步骤:

1)创建Timer 对象

2)调用schedule方法

3)传入TimerTask子类对象

代码演示如下:

Timer timer = new Timer();
timer.schedule(new TimerTask() {@Overridepublic void run() {for (int i = 0; i < 10; i++) {System.out.println(Thread.currentThread().getName() + "-->" + i);}}
}, 100, 100);

​文源网络,仅供学习之用,如有侵权,联系删除。

我整理了一套学习资料,涵盖Java虚拟机、spring框架、Java线程、数据结构、设计模式等等,免费提供给热爱Java的同学! 戳我主页查看获取方式。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/262105.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

入侵思路新手学习内容

1.入侵主机的思路 第一.先找定目标<网站或IP> 没有目标怎样入侵? 第二.找到目标是什么操作系统! 操作系统都不知道找漏洞,又怎样成入侵成功! 第三,找操作系统漏洞!如开放的端口,开放的服务等!!! 没找到漏洞怎样入侵? 第四.扫描端口!找有没有漏洞利用的端口! 端口就是…

matlab中如何提取等高线,在Python或MATLAB中从等高线图中提取数据

这是一个小型的Matlab脚本&#xff0c;可以完成这项工作(使用一些GUI&#xff0c;在图的斜角处读取guidlines)&#xff1a;%// Import the data:imdata importdata(your_picture_file);Gray rgb2gray(imdata.cdata);colorLim [-1 1]; %// this should be set manually%// Ge…

【Android Studio】分类整理res/Layouts中的布局文件(创建子目录)

好吧&#xff0c;这个功能需求也是因为作为一个重度强迫症患者&#xff0c;非常想要把layouts中的文件分类整理下。否则看到一堆Activity和Fragment等文件混在一起特别难受。更重要的原因是&#xff0c;如果你的工程交给别人维护&#xff0c;别人看到一堆布局文件压根不知道从哪…

从零开始学python项目_从零开始可以这样学python

从零开始学python第二章 面向对象第一篇 太原理工大学机器人团队20日打卡day9 ​ 当我们讨论python时不得不讨论到面向对象&#xff0c;而我身为机器人团队的一名成员&#xff0c;在平时设计的时候可以通过把机器人的各个部分设计成不同的对象以此来简化重复的函数引用。并且py…

GDI绘图基本步骤总结(经典)

一、获得绘图的窗口句柄 方法(详细参数及其调用可以看考MSDN)&#xff1a; 1、 HWND FindWindow(LPCTSTR lpClassName, LPCTSTR lpWindowName) HWND FindWindowEx(HWND hwndParent, HWND hwndChildAfter,LPCTSTR lpClassName, LPCTSTR lpWindowName) 2、 HWN…

SQL排序查询

1.建一张客户表&#xff0c;包含客户名称&#xff0c;联系人&#xff0c;电话号码&#xff0c;公司地址. 2.建一张订单表&#xff0c;包含订单编号&#xff0c;客户ID,供应商ID,订单金额&#xff0c;客户支付状态&#xff0c;供应商支付状态,订单日期. 3.建一张供应商表&#x…

php smarty框架案例,php封装的smarty类案例

这篇文章主要介绍了php封装的smarty类,针对Smarty的基本操作技巧进行了封装整理,具有一定参考借鉴价值,需要的朋友可以参考下具体如下&#xff1a;/*** Project: Smarty: the PHP compiling template engine* File: Smarty.class.php* SVN: $Id: Smarty.class.php 4848 2014-06…

使用pip安装BeautifulSoup4模块

1.测试是否安装了BeautifulSoup4模块 import bs4 print bs4 执行报错说明没有安装该模块 Traceback (most recent call last):File "D:\work_java\python\src\baike_spider\test.py", line 7, in <module>import bs4 ImportError: No module named bs4 2.使用p…

mysql8创建用户并授权_新特性解读 | 从 wireshark 看 MySQL 8.0 加密连接

作者&#xff1a;秦福朗爱可生 DBA 团队成员&#xff0c;负责项目日常问题处理及公司平台问题排查。热爱 IT&#xff0c;喜欢在互联网里畅游&#xff0c;擅长摄影、厨艺&#xff0c;不会厨艺的 DBA 不是好司机&#xff0c;didi~本文来源&#xff1a;原创投稿*爱可生开源社区出品…

ACM进阶

ACM队不是为了一场比赛而存在的&#xff0c;为的是队员的整体提高。大学期间&#xff0c;ACM队队员必须要学好的课程有&#xff1a;l C/C两种语言l 高等数学l 线性代数l 数据结构l 离散数学l 数据库原理l 操作系统原理l 计算机组成原理l 人工智能l 编译原理l 算法设计与分析除此…

[转 TDD] 如何坚持TDD:使用者出现的问题以及解决方案

原文地址&#xff1a;http://www.infoq.com/cn/articles/levison-TDD-adoption-strategy 转载于:https://www.cnblogs.com/cly84920/archive/2010/03/24/4426820.html

DP备份任务失败原因解析

以JDC为例&#xff0c;DP的备份任务失败troubleshooting流程为&#xff1a;1&#xff09;/etc/opt/omni/server/datalist下都是备份的job code。如果要查看一个job code&#xff0c;可以more 此文件夹下的某个datalist,输入如下&#xff1a;最上面的两个脚本pre和post&#xff…

mysql求表中年龄同张三,mysql子查询与连接查询

表结构以及数据&#xff1a;CREATE TABLEstudent (idint(11) NOT NULLAUTO_INCREMENT,namevarchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,ageint(11) NULL DEFAULT NULL,PRIMARY KEY(id) USING BTREE) ENGINE InnoDB AUTO_INCREMENT 13 CHARACT…

jenkins war包_Jenkins的安装和部署(jenkins教程)

一、jenkins的下载、安装以及环境的搭建部署。1.什么是jenkins以及它的作用&#xff1a;Jenkins 是一个可扩展的持续集成&#xff08;CI&#xff09;平台。它只是一个平台&#xff0c;真正运作的都是插件。Jenkins的主要作用&#xff1a;持续的监控软件版本发布/测试项目。监控…

.net Web网站转换成Web应用程序 备忘

1.新建Web应用程序&#xff0c;把Web网站代码全部粘贴进来2.添加所有原来引用3.【*】Web应用程序不再自动预编译App_Code文件夹&#xff0c;但是会编译任何文件夹下的类文件(除App_Code),所有给App_Code文件夹换个其它名字。4.【*】把第3部改名后文件夹下的所有文件&#xff0c…

div没有设置高度,背景颜色却无法显示

在设计网页时&#xff0c;设置了div为自动高度或不给height值&#xff0c;当div设置背景时在IE6可以显示背景颜色&#xff0c;但是IE7,8却不显示。 解决办法如下&#xff1a; 1、把height:auto;改成height:100%; overflow:hidden; 原理&#xff1a;IE6可以再不给高度的情况下自…

内存恶鬼drawRect

转载于:http://bihongbo.com/内存恶鬼drawRect 标题有点吓人&#xff0c;但是对于drawRect的评价倒是一点都不过分。在平日的开发中&#xff0c;随意覆盖drawRect方法&#xff0c;稍有不慎就会让你的程序内存暴增。下面我们来看一个例子。 去年的某天午后&#xff0c;北京的雾霾…

c#和python同一主机直接udp_为什么Python 如此之慢

原文:https://hackernoon.com/why-is-python-so-slow-e5074b6fe55b​hackernoon.comPython 正在爆炸般流行起来&#xff0c;它被用于DevOps, 数据处理&#xff0c;web开发和安全领域。但是在速度方面却没有取得过什么胜利。 Java在速度方面和C/C/C#/Python比起来如何&#xff…

matlab编程ode45,matlab 中ode45的源代码如何看懂

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼求常微分方程的数值解 ode45方法的源代码怎么看懂呢&#xff1f;四百多行 如何理解这些代码的核心思想 以方便未来自己使用呢&#xff1f;求大神指点迷津 感激不尽function varargout ode45(ode,tspan,y0,options,varargin)%ODE45…

N2 API

非常详细的N2API文档&#xff0c;以及N2的Wiki和讨论区&#xff0c;特此贴出&#xff0c;以备参考。 参考:http://consultingblogs.emc.com/jamesbroome/archive/2009/04/24/why-i-like-n2-cms.aspx 转载于:https://www.cnblogs.com/chenjunsheep/archive/2010/03/25/1695300.…