Java多线程应用总结
一、基本方法
进程和线程一样,都是实现并发的一个基本单位。线程是比进程更小的执行单位,线程是在进程的基础上进行的进一步划分。所谓多线程,是指一个进程在执行过程中可以产生多个更小的程序单元,这些更小的单元称为线程,这些线程可以同时存在、同时运行。
Tread类中的主要方法:
| 序 号 | 方法名称 | 类 型 | 描 述 |
| 1 | public Thread(Runnable target) | 构造 | 接收Runnable接口子类对象,实例化Thread对象 |
| 2 | public Thread(Runnable target, String name) | 构造 | 接收Runnable接口子类对象,实例化Thread对象,并设置线程名称 |
| 3 | public Thread(String name) | 构造 | 接收Runnable接口子类对象,并设置线程名称 |
| 4 | public static Thread currentThread() | 普通 | 返回目前正在执行的线程 |
| 5 | public final String getName() | 普通 | 返回线程的名称 |
| 6 | public final int getPriority() | 普通 | 返回线程的优先级 |
| 7 | public boolean isInterrupted() | 普通 | 判断目前线程是否被中断,如果是返回true,否则返回false |
| 8 | public final boolean isAlive() | 普通 | 判断线程是否在活动,如果是返回true,否则返回false |
| 9 | public final void join() throws Interrupted Exception | 普通 | 等待线程死亡 |
| 10 | public final synchronized void join(long millis) throws Interrupted Exception | 普通 | 等待millis毫秒后,线程死亡 |
| 11 | public void run() | 普通 | 执行线程 |
| 12 | public final void setName(String name) | 普通 | 设定线程名称 |
| 13 | public final void setPriority(int newPriority ) | 普通 | 设定线程的优先级 |
| 14 | public static void sleep(long millis) throws InterruptedException | 普通 | 使目前正在执行的线程休眠millis毫秒 |
| 15 | public void start() | 普通 | 开始执行线程 |
| 16 | public String toString() | 普通 | 返回代表线程的字符串 |
| 17 | public static void yield() | 普通 | 将目前正在执行的线程暂停,允许其他的线程执行 |
| 18 | public final void setDaemon(boolean on) | 普通 | 将一个线程设置成后台运行 |
二、多线程的实现方式及其异同
方式一:
package test.thread.share.first;
class MyThread extends Thread {
private int ticket = 5;
public void run(){
for(int i = 0; i<10; i++)
if(ticket > 0){
System.out.println("买票: ticket =" + ticket--);
}
}
}
public class ThreadShare {
public static void main(String[] args) {
MyThread mt1 = new MyThread();
MyThread mt2 = new MyThread();
MyThread mt3 = new MyThread();
mt1.start();
mt2.start();
mt3.start();
}
}
方式二:
package test.thread.share.second;
class MyThread implements Runnable{
private int ticket = 5;
public void run(){
for(int i=0; i<10; i++){
if(ticket > 0){
System.out.println("买票 ticket = " + ticket--);
}
}
}
}
public class ThreadShare {
public static void main(String[] args) {
new Thread(new MyThread()).start();
new Thread(new MyThread()).start();
new Thread(new MyThread()).start();
}
}
方式三:
在方式二的基础上略微改动一下。
package test.thread.share.second;
class MyThread implements Runnable{
private int ticket = 5;
public void run(){
for(int i=0; i<10; i++){
if(ticket > 0){
System.out.println("买票 ticket = " + ticket--);
}
}
}
}
public class ThreadShare {
public static void main(String[] args) {
// new Thread(new MyThread()).start();
// new Thread(new MyThread()).start();
// new Thread(new MyThread()).start();
MyThread my = new MyThread();
new Thread(my).start();
new Thread(my).start();
new Thread(my).start();
}
}
方式一与方式二本质上没有什么差别,但是方式三却实现了真正的资源共享,其关键在于Thread类的不同构造方式,new Thread(); 与 new Tread(Runnable target); 这两种方式最终是要调用start()方法,而start()方法是在调用run()方法。因此,关键取决于所调用的run()方法。只有采用new Tread(Runnable target); 这种方式才有可能让传入的参数引用指向同一个run()方法的地址引用,这种机制本质上由于Runnable接口没有定义start()方法,而Thread()构造函数(也可以包含参数)或者说Thread类的内在能力仍然是开辟新的线程任务(引用),一视同仁,至于传入的是什么它不管,只要合法就行,只要最终可以正确的引用到run()方法就Ok了。
三 关于join()
我个人的理解是让当前的线程任务保持join,也就是在一起,不可分割,一次执行完。有点类似于synchronized()的功能,但是synchronized()的参数不能为static object。
public static void main(String[] args) {
MyThread mt = new MyThread();
Thread t = new Thread(mt, "线程");
t.start();
for(int i=0; i<50; i++){
if(i>10){
try{
t.join();
} catch(Exception e){
}
System.out.println("Main 线程运行 ---> " + i);
}
}
}
上面这段代码中,t线程执行完后,才轮到Main 线程执行,且for循环一次执行完,中间不会穿插着t线程的任务。正常情况下,如果不采用join()方法的话,那么JVM会让t线程与main线程交替随机执行(并行执行)。
四、等待与唤醒
在生产者与消费者模式中会用到同步机制与等待唤醒机制,前者主要针对于局部,而后者更多的是关注整体的布局与策略。二者的配合可以让生产者与消费者模式稳健的运作。
class Info {
private String name = "张三";
private String content = "管理员";
private boolean flag = false;
public synchronized void set(String name, String content){
if(!flag){
try{
super.wait();
} catch(InterruptedException ex){
ex.printStackTrace();
}
}
this.setName(name);
try{
Thread.sleep(300);
} catch(InterruptedException ex){
ex.printStackTrace();
}
this.setContent(content);
flag = false;
super.notify();
}
public synchronized void get(){
if(flag){
try{
super.wait();
} catch(InterruptedException ex){
ex.printStackTrace();
}
}
try{
Thread.sleep(300);
} catch(InterruptedException ex){
ex.printStackTrace();
}
System.out.println(this.getName() + "-->" + this.getContent());
flag = true;
super.notify();
}
public String getName(){
return name;
}
public void setName(String name){
this.name = name;
}
public String getContent(){
return content;
}
public void setContent(String content){
this.content = content;
}
}
super.notify()的含义是调用Object类的静态方法notify方法,它会唤醒第一个等待的线程执行,而notifyAll()会唤醒所有的等待线程。wait()方法会让当前执行的线程进入到等待状态,也可以理解为休眠状态。
Java多线程应用总结的更多相关文章
- 40个Java多线程问题总结
前言 Java多线程分类中写了21篇多线程的文章,21篇文章的内容很多,个人认为,学习,内容越多.越杂的知识,越需要进行深刻的总结,这样才能记忆深刻,将知识变成自己的.这篇文章主要是对多线程的问题进行 ...
- Java多线程基础知识篇
这篇是Java多线程基本用法的一个总结. 本篇文章会从一下几个方面来说明Java多线程的基本用法: 如何使用多线程 如何得到多线程的一些信息 如何停止线程 如何暂停线程 线程的一些其他用法 所有的代码 ...
- Java多线程系列--“JUC锁”03之 公平锁(一)
概要 本章对“公平锁”的获取锁机制进行介绍(本文的公平锁指的是互斥锁的公平锁),内容包括:基本概念ReentrantLock数据结构参考代码获取公平锁(基于JDK1.7.0_40)一. tryAcqu ...
- Java多线程系列--“JUC锁”04之 公平锁(二)
概要 前面一章,我们学习了“公平锁”获取锁的详细流程:这里,我们再来看看“公平锁”释放锁的过程.内容包括:参考代码释放公平锁(基于JDK1.7.0_40) “公平锁”的获取过程请参考“Java多线程系 ...
- Java多线程--让主线程等待子线程执行完毕
使用Java多线程编程时经常遇到主线程需要等待子线程执行完成以后才能继续执行,那么接下来介绍一种简单的方式使主线程等待. java.util.concurrent.CountDownLatch 使用c ...
- Java多线程 2 线程的生命周期和状态控制
一.线程的生命周期 线程状态转换图: 1.新建状态 用new关键字和Thread类或其子类建立一个线程对象后,该线程对象就处于新生状态.处于新生状态的线程有自己的内存空间,通过调用start方法进入就 ...
- java 多线程 1 线程 进程
Java多线程(一).多线程的基本概念和使用 2012-09-10 16:06 5108人阅读 评论(0) 收藏 举报 分类: javaSE综合知识点(14) 版权声明:本文为博主原创文章,未经博 ...
- 一起阅读《Java多线程编程核心技术》
目录 第一章 Java多线程技能 (待续...)
- 第一章 Java多线程技能
1.初步了解"进程"."线程"."多线程" 说到多线程,大多都会联系到"进程"和"线程".那么这两者 ...
- java从基础知识(十)java多线程(下)
首先介绍可见性.原子性.有序性.重排序这几个概念 原子性:即一个操作或多个操作要么全部执行并且执行的过程不会被任何因素打断,要么都不执行. 可见性:一个线程对共享变量值的修改,能够及时地被其它线程看到 ...
随机推荐
- dedecms系统后台登陆提示用户名密码不存在
dedecms最近被曝有非常多的安全漏洞,最近有些用户反应后台管理员账号密码没有修改但无法正常登陆,提示用户名不存在,经研究发现是程序漏洞管理员被直接篡改,解决方案如下. 工具/原料 dedecms ...
- [拾 得]pipe和xargs的恩怨情仇
Photo by Joshua Sortino on Unsplash 坚持知识分享,该文章由Alopex编著, 转载请注明源地址: http://www.cnblogs.com/alopex/ ...
- TCP三次握手和四次挥手过程
1.三次握手 (1)三次握手的详述 首先Client端发送连接请求报文,Server段接受连接后回复ACK报文,并为这次连接分配资源.Client端接收到ACK报文后也向Server段发生ACK报文, ...
- Postgresql中string转换成timestamp类型
Mybatis+Postgresql TO_DATE(#{startTime}, 'YYYY-MM-DD') AND op_date <![CDATA[>= ]]> TO_TIME ...
- Mac下用SSH连接远程Linux或Mac服务器
1.打开Mac终端 2.切换到root登录 输入命令:sudo -i,然后输入本机密码 p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 14.0px &qu ...
- Socket与ServerSocket
ServerSocket: 用于打开服务端口,等待客户端连接,运行在服务端. Socket: 用于连接指定服务器的指定端口,运行在客户端. flush是输出到缓冲区,缓冲区没满的话不发送,close的 ...
- VM安装Ubuntu问题合集(无法联网、中文界面设置、中文输入法etc)
经常使用VM安装Ubuntu,安装系统的步骤跟着系统提示一步步下来就行,但总是遇到一些问题,这里记录一下常遇到的问题,以及自己解决的办法: 1.无法联网: 状况:Ubuntu不能联网,联网地方一直在闪 ...
- 在windows下进行Kafka单机测试
环境:win10 kafka版本:kafka_2.11-0.10.0.0 zookeeper版本:zookeeper-3.4.11 1. 开启zookeeeper server cmd下 : .\bi ...
- sersync+rsync同步
(一)目标服务器(rsync):10.60.50.192 1.安装rsync yum -y install rsync 2.创建rsyncd.conf配置文件 vi /etc/rsyncd.conf ...
- python_如何快速找打字典中公共key
场景实例: 西班牙足球联赛,每轮球员进球统计: 第一轮:{'1':1,'2':4,'5':2,'7':3} 第一轮:{'2':1,'5':4,'6':2,'3':3} 第一轮:{'1':1,'4':4 ...