27 多线程(一)——创建进程的三种方法、线程锁(同步synchornized与lock)
线程的流程
线程的创建
有三种方法,重点掌握前两种:
- 继承Thread类
- 实现Runnable接口(推荐使用:避免单继承的局限性)
- 实现Callable接口
根据java的思想,要少用继承,多用实现。
第一种:继承Thread类
继承Thread的类必需重写run方法,run方法即为线程体。
当程序执行到start()时,不会等这句执行完,继续往下走,main方法与t中的run方法并发执行。
代码:
- package _20191203;
- /**
- * 创建线程的方法一:继承Thread
- * @author UID
- *
- */
- public class ThreadTest extends Thread{
- public static void main(String[] args) {
- ThreadTest t = new ThreadTest();
- t.start();//当程序执行到这里时,不会等这句执行完,继续往下走,main方法与t中的run方法并发执行
- for(int i = 0;i < 500;i++) {
- System.out.println("一边听歌");
- }
- }
- @Override
- public void run() { //必需重写run方法
- super.run();
- for(int i = 0;i < 800;i++) {
- System.out.println("一边敲代码");
- }
- }
- }
看看效果(结果有所截取):
- 一边听歌
- 一边听歌
- 一边听歌
- 一边听歌
- 一边听歌
- 一边听歌
- 一边听歌
- 一边听歌
- 一边听歌
- 一边敲代码
- 一边敲代码
- 一边敲代码
- 一边敲代码
- 一边敲代码
- 一边敲代码
- 一边敲代码
- 一边敲代码
- 一边听歌
- 一边听歌
- 一边听歌
- 一边听歌
- 一边听歌
- 一边听歌
- 一边听歌
- 一边听歌
- 一边敲代码
- 一边敲代码
- 一边敲代码
- 一边敲代码
- 一边敲代码
- 一边敲代码
- 一边敲代码
- 一边敲代码
第二种:实现Runnable接口
类直接实现Runnable接口,在类中写run方法,通过代理类Thread来调用它即可开启线程。
只使用一次的对象推荐使用匿名对象:
- new Thread(new xxx()).start();//xxx为实现了Runnable接口的类
代码:
- package _20191203;
- /**
- * 创建线程的方法一:继承Thread
- * @author UID
- *
- */
- public class ThreadTest implements Runnable{
- public static void main(String[] args) {
- new Thread(new ThreadTest()).start();//对象只使用一次时推荐使用匿名对象
- for(int i = 0;i < 200;i++) {
- System.out.println("一边听歌");
- }
- }
- @Override
- public void run() { //必需重写run方法
- for(int i = 0;i < 200;i++) {
- System.out.println("一边敲代码");
- }
- }
- }
第三种:实现Callable接口
这种方式,一般中小企业不会用到,它是一种高级方法,一般也要工作3到5年提升时才会学到,在这里只做了解,面试用。
流程:
需要做线程的类实现Callable接口,如:
一般要写上泛型。
- public class Test implements Callable<泛型>{}
实现Callable的类必需重写call方法,相当于run方法:
他需要有返回值。
- public <泛型> call() Throws Exception{}
然后在使用线程的方法中(如main方法):
主要有以下步骤
- //新建执行服务对象
ExecutorService es = Executors.newFixedThreadPool(线程数量);- //提交执行
Future<泛型> result1 = es.submit(r1);//r1为实现了Callable接口的示例,有几个就写几行这行代码- //获取结果
泛型对应的类型 res1 = result1.get();如:Integer res1 = result1.get();- //关闭服务
es.shutdownNow();
龟兔晒跑的示例:
- package _20191203;
- import java.util.concurrent.Callable;
- import java.util.concurrent.ExecutionException;
- import java.util.concurrent.ExecutorService;
- import java.util.concurrent.Executors;
- import java.util.concurrent.Future;
- /**
- * 多线程,龟兔赛跑
- * @author UID
- *
- */
- public class Race implements Callable<Integer>{
- private String winner;
- @Override
- public Integer call() throws Exception{
- // TODO Auto-generated method stub
- for (int step = 1; step <= 100; step++) {
- System.out.println(Thread.currentThread().getName()+"--->"+step);
- if(winner != null) {
- break;
- }else if(step==100) {
- System.out.println("胜利者:"+Thread.currentThread().getName());
- return step;
- }
- }
- return null;
- }
- public static void main(String[] args) {
- Race r1 = new Race();
- Race r2 = new Race();
- //创建执行服务
- ExecutorService es = Executors.newFixedThreadPool(2);
- //提交执行
- Future<Integer> result1 = es.submit(r1);
- Future<Integer> result2 = es.submit(r2);
- //获取结果
- try {
- Integer res1 = result1.get();
- } catch (InterruptedException | ExecutionException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- try {
- Integer res2 = result2.get();
- } catch (InterruptedException | ExecutionException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- //关闭服务
- es.shutdownNow();
- }
- }
线程Thread类的构造方法与不安全线程
Thread(Runnable target,String name);
通过该构造方法创建线程时可以给线程起一个名字,这个名字可以使用Thread.currentThread().getName()来获取
例子:
抢票模拟,线程不安全型:
- package _20191203;
- /**
- * 模拟抢票:此代码线程不安群
- * @author UID
- *
- */
- public class Thread12306 implements Runnable{
- private int source = 100;
- public void run() {
- while(source>0) {
- source--;
- System.out.println(Thread.currentThread().getName()+" 抢到了票!还剩:"+source);
- try {
- Thread.sleep(100);
- } catch (InterruptedException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- }
- public static void main(String[] args) {
- Thread t1 = new Thread(new Thread12306(),"线程1");
- Thread t2 = new Thread(new Thread12306(),"线程2");
- Thread t3 = new Thread(new Thread12306(),"线程3");
- t1.start();
- t2.start();
- t3.start();
- }
- }
运行结果,线程不安全的后果:
27 多线程(一)——创建进程的三种方法、线程锁(同步synchornized与lock)的更多相关文章
- Linux启动新进程的三种方法
程序中,我们有时需要启动一个新的进程,来完成其他的工作.下面介绍了三种实现方法,以及这三种方法之间的区别. 1.system函数-调用shell进程,开启新进程system函数,是通过启动shell进 ...
- cocos2dx中创建动画的三种方法
1.最最原始的方法,先创建动画帧,再创建动画打包(animation),再创建动画(animate) 第一步: 创建动画帧:CCSpriteFrame,依赖于原始的资源图片(xx.png,xx.jpg ...
- Linux中创建Daemon进程的三种方法
什么是daemon进程? Unix/Linux中的daemon进程类似于Windows中的后台服务进程,一直在后台运行运行,例如http服务进程nginx,ssh服务进程sshd等.注意,其英文拼写为 ...
- MySQL创建用户的三种方法 (并授权)转
前言:MySQL创建用户的方法分成三种:INSERT USER表的方法.CREATE USER的方法.GRANT的方法. 一.账号名称的构成方式 账号的组成方式:用户名+主机(所以可以出现重复的用户名 ...
- ORM 创建manytomay的三种方法 反向查询 和一些 双下方法版学员管理系统3
老师信息管理 三种创建多对对外键的方式常用第二种和第三种 思考 三种方式创建多对多外键方式及其优缺点. 外键的查询和使用 1外键的创建: 在数据库表中的表现形式 如何连表查询和使用 表里边: s ...
- MySQL创建用户的三种方法
前言:MySQL创建用户的方法分成三种:INSERT USER表的方法.CREATE USER的方法.GRANT的方法. 一.账号名称的构成方式 账号的组成方式:用户名+主机(所以可以出现重复的用户名 ...
- Jenkins 批量创建任务的三种方法
最近,要搭建多套测试环境,需要把 Jenkins 中 dev 视图下的所有任务批量复制到 sit 等视图下. 说明 Jenkins 任务名称规则为:[测试环境标识]-[工程名称],如:dev-daod ...
- [HTML/CSS]创建新元素的三种方法
第一种:通过text/HTML var txt1="<h1>Text.</h1>"; 第二种:通过jQuery var txt2=$("<h ...
- Java创建数组的三种方法
■ 第一种: int[] arr=new int[6]; arr[0] = 1; arr[1] = 2 arr[2] = 3; arr[3] = 4; arr[4] = 5; arr[5] = 6; ...
随机推荐
- inflection point
http://blog.thefirehoseproject.com/posts/learn-to-code-and-be-self-reliant/ kill will develop 1.repe ...
- (尚019)Vue基于脚手架编写项目
vue_demo目录结构截图: (1)图一 (2).图二 (3).图三 (四).图四 (5).图五 (6).图六 (7).图七 不能随便改入口文件的名字,因为已经配置好了 (8).图八 (9).图九 ...
- Redis存储Sortedset
与set相比Sortedset多了一个数字与set中的各个元素相关联. 存储结构: 1.添加元素: 添加元素的时候元素一定不能相同,如果已存在该元素,表示插入失败返回0,成功返回1,但是不同元素的数字 ...
- 使用git_stats 统计分析git 仓库代码&& 集成webhook
前几天写过一个使用gitstats 统计分析代码的,但是那个因为开发的问题,对于直接和容器集成是有问题的,统计需要进入容器执行 命令,对于自动构建的还不是很方便,所以使用了git_stats 项目 ...
- 洛谷 P2850 [USACO06DEC]虫洞Wormholes 题解
P2850 [USACO06DEC]虫洞Wormholes 题目描述 While exploring his many farms, Farmer John has discovered a numb ...
- 3、kafka工作流程
一.kafka各成员 kafka: 分布式消息系统,将消息直接存入磁盘,默认保存一周. broker: 组成kafka集群的节点,之间没有主从关系,依赖zookeeper来协调,broker负责满息的 ...
- Balanced Ternary String(贪心+思维)
题目链接:Balanced Ternary String 题目大意:给一个字符串,这个字符串只由0,1,2构成,然后让替换字符,使得在替换字符次数最少的前提下,使新获得的字符串中0,1,2 这三个字符 ...
- Linux查看当前操作系统版本信息
.Linux查看当前操作系统版本信息 cat /proc/version Linux version -.el6.x86_64 (mockbuild@c1bm.rdu2.centos.org) (gc ...
- .getCellType()的几种类型值
CellType 类型 值 CELL_TYPE_NUMERIC 数值型 0 CELL_TYPE_STRING 字符串型 1 CELL_TYPE_FORMULA 公式型 2 CEL ...
- #C++初学记录(动态规划(dynamic programming)例题1 钞票)
浅入动态规划 dynamic programming is a method for solving a complex problem by breaking it down into a coll ...