Java高并发之线程基本操作
结合上一篇同步异步,这篇理解线程操作。
1、新建线程。不止thread和runnable,Callable和Future了解一下
package com.thread; import java.text.SimpleDateFormat;
import java.util.Date;
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;
import java.util.concurrent.FutureTask; /**
* 线程启动
* @author Administrator
*
*/
public class StartThreadTest extends Thread{ @Override
public void run(){
for (int i = 0; i < 3; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"i:"+i);
}
} public static void main(String[] args) throws InterruptedException {
//继承 Thread 类的线程启动方式
StartThreadTest test = new StartThreadTest();
StartThreadTest test2 = new StartThreadTest();
System.out.println("开始执行线程1......");
test.start();test2.start();
test.join();test2.join(); //join方法会让main线程等待test、test2线程执行完,如果对执行结果不感冒,则不用join
System.out.println("结束执行线程1......");
}
//******************************************************************************************************
static class startThread2 implements Runnable{ @Override
public void run() {
for (int i = 0; i < 3; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("i:"+i);
}
} public static void main(String[] args) {
//实现 Runnable 接口的线程启动方式
startThread2 thread2 = new startThread2();
Thread t = new Thread(thread2);
t.start();
}
}
//******************************************************************************************************
/**
* Callable 用于获取线程执行结果
* 多个Callable耗时是每个线程的总耗时
* @author Administrator
*
*/
static class startThread3 implements Callable<String>{ @Override
public String call() throws Exception {
int result = 0;
for (int i = 0; i < 3; i++) {
Thread.sleep(1000);
result += i;
}
return String.valueOf(result);
} public static void main(String[] args) throws Exception {
SimpleDateFormat format = new SimpleDateFormat("hh:mm:ss");
System.out.println("开始时间:"+format.format(new Date())); Callable<String> call = new Callable<String>() { @Override
public String call() throws Exception {
int result = 0;
for (int i = 0; i < 5; i++) {
Thread.sleep(1000);
result += i;
}
return String.valueOf(result);
}
};
ExecutorService service = Executors.newSingleThreadExecutor();
Future<String> f = service.submit(call);
System.out.println(f.get());
service.shutdown();
System.out.println("时间1:"+format.format(new Date()));
//实现 Callable 接口的线程启动方式
startThread3 thread3 = new startThread3();
System.out.println("开始执行线程......");
String result = thread3.call();
System.out.println("结束执行线程。result:"+result); //result:3 【线程执行完获取结果,会阻塞当前线程】
System.out.println("时间2:"+format.format(new Date())); //开始时间:05:04:21
//10
//时间1:05:04:26
//开始执行线程......
//结束执行线程。result:3
//时间2:05:04:29 }
}
//******************************************************************************************************
/**
* Future 用于获取异步线程的结果,总耗时是最长耗时的线程
* @author Administrator
*
*/
static class startThread4 {
public static void main(String[] args) throws InterruptedException, ExecutionException {
SimpleDateFormat format = new SimpleDateFormat("hh:mm:ss");
System.out.println("开始时间:"+format.format(new Date())); //操作1:耗时3秒
FutureTask<String> futureTask = new FutureTask<>(new startThread3());
new Thread(futureTask).start(); //操作2:耗时5秒
Callable<String> call = new Callable<String>() { @Override
public String call() throws Exception {
int result = 0;
for (int i = 0; i < 5; i++) {
Thread.sleep(1000);
result += i;
}
return String.valueOf(result);
}
};
FutureTask<String> futureTask2 = new FutureTask<>(call);
new Thread(futureTask2).start(); System.out.println("操作1返回:"+futureTask.get());
System.out.println("操作2返回:"+futureTask2.get()); System.out.println("结束时间:"+format.format(new Date())); //开始时间:04:50:53
//操作1返回:3
//操作2返回:10
//结束时间:04:50:58
}
}
}
2、停止线程。volatile和interrupt各显神通
package com.thread; import java.text.SimpleDateFormat;
import java.util.Date; /**
* 关闭线程
* @author Administrator
*
*/
public class StopThreadTest extends Thread { static int i = 0;
static int j = 0; @Override
public void run() {
//同步操作确保i,j都自增1
synchronized (this) {
i++;
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
j++;
}
} public static void main(String[] args) throws InterruptedException {
StopThreadTest test = new StopThreadTest();
test.start();
Thread.sleep(1000);
//Thread.stop():强制关闭对象获取的锁,破坏线程数据安全
test.stop();
test.join();
System.out.println("i:"+i+";j:"+j); //i:1;j:0 } static class volatileStopThreadTest extends Thread{ volatile boolean exitFlag = false; //volatile确保可见性
static SimpleDateFormat format = new SimpleDateFormat("hh:mm:ss"); @Override
public void run() {
System.out.println("run线程开始时间:"+format.format(new Date()));
while(!exitFlag){
System.out.println("run方法进入时间:"+format.format(new Date()));
//同步操作确保i,j都自增1
synchronized (this) {
i++;
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
j++;
}
}
System.out.println("run线程结束时间:"+format.format(new Date()));
} public static void main(String[] args) throws InterruptedException {
System.out.println("主线程开始时间:"+format.format(new Date()));
volatileStopThreadTest test = new volatileStopThreadTest();
test.start();
Thread.sleep(1000);
System.out.println("主线程休眠1秒:"+format.format(new Date()));
test.exitFlag = true;
test.join();
System.out.println("i:"+i+";j:"+j); //主线程开始时间:05:17:03
//run线程开始时间:05:17:03
//run方法进入时间:05:17:03
//主线程休眠1秒:05:17:04 【标志位exitFlag改了,run方法依然在执行,只是下次竞争到锁都不执行run】
//run线程结束时间:05:17:13
//i:1;j:1 【确保了线程数据安全】 }
} static class interruptStopThreadTest extends Thread{ static SimpleDateFormat format = new SimpleDateFormat("hh:mm:ss"); @Override
public void run() {
System.out.println(Thread.currentThread().getName()+"-线程进入run开始时间:"+format.format(new Date()));
while(true){
//判断线程是否已经被中断,如果被中断,则下次竞争时直接退出
if(Thread.currentThread().isInterrupted()){
System.out.println(Thread.currentThread().getName()+"-线程已被中断......,中断时间:"+format.format(new Date()));
//退出while循环
break;
}
//同步操作确保i,j都自增1
synchronized (this) {
i++;
try {
Thread.sleep(10000);
System.out.println(Thread.currentThread().getName()+"-线程休眠10秒......");
} catch (InterruptedException e) {
e.printStackTrace();
System.out.println("中断标志:"+Thread.currentThread().isInterrupted());
//阻塞过程中被中断,test.interrupt()方法设置的中断标识会立刻变成false,需要重新设置中断标识
Thread.currentThread().interrupt();
System.out.println(Thread.currentThread().getName()+"-线程被中断了!");
}
j++;
}
//打印:
//Thread-0-线程进入run开始时间:10:01:34
//java.lang.InterruptedException: sleep interrupted
// at java.lang.Thread.sleep(Native Method)
// at com.thread.StopThreadTest$interruptStopThreadTest.run(StopThreadTest.java:103)
//中断标志:false
//Thread-0-线程被中断了!
//Thread-0-线程已被中断......,中断时间:10:01:36
//i:1;j:1 【线程数据安全】 // synchronized (this) {
// i++;
// try {
// for (int z = 0; z < 10; z++) {
// if(z==9){
// int a = 1/0;
// System.out.println("模拟异常");
// }
// }
// Thread.sleep(5000); //异常后的语句不会执行
// } catch (Exception e) {
// e.printStackTrace();
// //线程执行过程中抛出了异常,通过设置中断标识,控制下次竞争
// Thread.currentThread().interrupt();
// System.out.println(Thread.currentThread().getName()+"-线程被中断了!");
// }
// j++;
// }
//打印:
//Thread-0-线程进入run开始时间:10:08:43
//Thread-0-线程被中断了!
//java.lang.ArithmeticException: / by zeroThread-0-线程已被中断......,中断时间:10:08:43 // at com.thread.StopThreadTest$interruptStopThreadTest.run(StopThreadTest.java:126)
//i:1;j:1 【线程数据安全】 }
} public static void main(String[] args) throws InterruptedException {
interruptStopThreadTest test = new interruptStopThreadTest();
test.start();
Thread.sleep(2000);
test.interrupt(); //中断线程 【设置中断标志,通过isInterrupted()控制竞争】
test.join();
System.out.println("i:"+i+";j:"+j);
}
}
}
3、线程挂起和继续执行。suspend和resume谨慎使用
package com.thread; /**
* 线程挂起与继续执行
* 不推荐用:
* 1、锁得不到释放,如果第二个线程先于第一个线程执行resume之前执行start,将造成锁永久等待
* 2、锁住的共享资源如果暗含同步方法,将导致其他线程使用该同步方法等待
* @author Administrator
*
*/
public class SuspendANDresumeThreadTest extends Thread{ volatile int i = 0; @Override
public void run(){
while(true){
synchronized(this){
i++;
System.out.println(Thread.currentThread().getName()+"-i:"+i);
}
}
} public static void main(String[] args) throws InterruptedException {
SuspendANDresumeThreadTest test = new SuspendANDresumeThreadTest();
SuspendANDresumeThreadTest test2 = new SuspendANDresumeThreadTest();
test.start();
Thread.sleep(1);
//test线程挂起后,占有的锁不会释放,导致test2线程一直处于阻塞态
test.suspend();
// test2.start();
// test.join();
//另外:查看println源码得知该方法是同步方法,在test占有锁的同时,导致println()也被占有,从而main线程无法执行下面的打印语句
System.out.println("该句无法打印!"); }
}
4、等待线程结束和谦让。join和yield
package com.thread; import java.text.SimpleDateFormat;
import java.util.Date; /**
* join:当前线程等待执行join的线程执行完
* yield:执行yield的线程让出占用的锁
* @author Administrator
*
*/
public class JoinANDyieldThreadTest extends Thread{ static SimpleDateFormat format = new SimpleDateFormat("hh:mm:ss"); @Override
public void run(){
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName()+"-i:"+i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} public static void main(String[] args) throws InterruptedException {
JoinANDyieldThreadTest test = new JoinANDyieldThreadTest();
JoinANDyieldThreadTest test2 = new JoinANDyieldThreadTest(); // test.start();
// Thread.sleep(3000);
// test.yield();
// test2.start(); //Thread-0-i:0
//Thread-0-i:1
//Thread-0-i:2
//Thread-0-i:3 【执行test.yield()后,test依然抢到了锁】
//Thread-1-i:0
//Thread-1-i:1
//Thread-0-i:4 test.setPriority(MIN_PRIORITY); //低优先级
test2.setPriority(MAX_PRIORITY); //高优先级
System.out.println("开始时间:"+format.format(new Date()));
test.start();
Thread.sleep(3000);
test.yield();
test2.start();
test.join();
test2.join(); //确保下面的打印在test和test2执行完后执行
System.out.println("结束时间:"+format.format(new Date()));
//Thread-0-i:0
//Thread-0-i:1
//Thread-0-i:2
//Thread-0-i:3 【test设置低优先级依然抢到了锁】
//Thread-1-i:0
//Thread-0-i:4
//Thread-1-i:1
//Thread-0-i:5 }
}
5、线程等待和唤醒。wait和notify
package com.thread; /**
* wait 和 notify 设计生产者与消费者模式
* 锁的选用:线程共享的变量
* wait 和 notify时机的运用,确保先生产后消费
* @author Administrator
*
*/
public class WaitANDnotifyThreadTest {
private static Integer count = 0; // 数据仓库计数
private final static Integer FULL = 5; // 数据仓库最大存储量
private static String lock = "lock"; // 锁标识
// Object obj = new Object(); //锁标识 public static void main(String[] args) {
new Thread(new Producer(), "product1").start();
new Thread(new Consumer(), "consumer1").start();
new Thread(new Producer(), "product2").start();
new Thread(new Consumer(), "consumer2").start();
} // 生产者
static class Producer implements Runnable {
@Override
public void run() {
for (int i = 0; i < 5; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
synchronized (lock) {
while (count == FULL) {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
count++;
System.out.println(Thread.currentThread().getName() + "-produce:: " + count);
// 唤醒lock锁上的所有线程
lock.notifyAll();
}
}
}
} // 消费者
static class Consumer implements Runnable {
@Override
public void run() {
for (int i = 0; i < 5; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
synchronized (lock) {
// 如果首次消费者竞争得到锁,进入后等待
while (count == 0) {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
count--;
System.out.println(Thread.currentThread().getName() + "-consume:: " + count);
lock.notifyAll();
}
}
}
}
}
Java高并发之线程基本操作的更多相关文章
- java高并发之线程池
Java高并发之线程池详解 线程池优势 在业务场景中, 如果一个对象创建销毁开销比较大, 那么此时建议池化对象进行管理. 例如线程, jdbc连接等等, 在高并发场景中, 如果可以复用之前销毁的对 ...
- 1.6 JAVA高并发之线程池
一.JAVA高级并发 1.5JDK之后引入高级并发特性,大多数的特性在java.util.concurrent 包中,是专门用于多线程发编程的,充分利用了现代多处理器和多核心系统的功能以编写大规模并发 ...
- Java高并发之线程池详解
线程池优势 在业务场景中, 如果一个对象创建销毁开销比较大, 那么此时建议池化对象进行管理. 例如线程, jdbc连接等等, 在高并发场景中, 如果可以复用之前销毁的对象, 那么系统效率将大大提升. ...
- Java高并发之锁优化
本文主要讲并行优化的几种方式, 其结构如下: 锁优化 减少锁的持有时间 例如避免给整个方法加锁 public synchronized void syncMethod(){ othercode1(); ...
- java高并发之锁的使用以及原理浅析
锁像synchronized同步块一样,是一种线程同步机制.让自Java 5开始,java.util.concurrent.locks包提供了另一种方式实现线程同步机制——Lock.那么问题来了既然都 ...
- Java高并发之无锁与Atomic源码分析
目录 CAS原理 AtomicInteger Unsafe AtomicReference AtomicStampedReference AtomicIntegerArray AtomicIntege ...
- Java高并发之设计模式
本文主要讲解几种常见并行模式, 具体目录结构如下图. 单例 单例是最常见的一种设计模式, 一般用于全局对象管理, 比如xml配置读写之类的. 一般分为懒汉式, 饿汉式. 懒汉式: 方法上加synchr ...
- Java高并发之同步异步
1.概念理解: 2.同步的解决方案: 1).基于代码 synchronized 关键字 修饰普通方法:作用于当前实例加锁,进入同步代码前要获得当前实例的锁. 修饰静态方法:作用于当前类对象加锁,进入同 ...
- Java 高并发之魂
前置知识 了解Java基本语法 了解多线程基本知识 知识介绍 Synchronized简介:作用.地位.不控制并发的后果 两种用法:对象锁和类锁 多线程访问同步方法的7种情况:是否是static.Sy ...
随机推荐
- React.js 小书 Lesson5 - React.js 基本环境安装
作者:胡子大哈 原文链接:http://huziketang.com/books/react/lesson5 转载请注明出处,保留原文链接和作者信息. 安装 React.js React.js 单独使 ...
- HDU 5371——Hotaru's problem——————【manacher处理回文】
Hotaru's problem Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) ...
- Day6 下(
T1 模拟,80? #include<iostream> #include<cstring> #include<queue> #include<algorit ...
- [转]Linq语法一
LINQ即语言集成查询,是.NET Framework 3.5中新增的功能.其功能类似于数据库中的SQL语句(实际上LINQ就是针对.NET Framework的SQL):提供标准的.易于学习的查询和 ...
- DOS常见命令
dir: 显示一个目录中的文件和子目录 md: 创建目录 rd: 删除目录 cd: 进入指定目录 cd..: 退回到上级目录 cd\: 退回到根目录 del: 删除文件 set: 显示.设置.删除cm ...
- C语言的各种输入情况介绍(ACM中常用到)
1.最简单的输入输出形式: 计算a+b的值: scanf("%d%d",&a,&b); printf("%d\n",a+b);--------- ...
- js获取文件上传进度
js获取文件上传进度: <input name="file" id="FileUpload" type="file" /> &l ...
- 自定义滑块Vue组件
<div class="audio"> <audio id="audio" ref="audio" src="h ...
- 【起航计划 027】2015 起航计划 Android APIDemo的魔鬼步伐 26 App->Preferences->Preferences from XML 偏好设置界面
我们在前面的例子Android ApiDemo示例解析(9):App->Activity->Persistent State 介绍了可以使用Shared Preferences来存储一些状 ...
- hp zbook15G2 nVidia K1100M显卡在ubuntu linux下闪屏问题
我的hp zbook15G2有一块nVidia K1100M显卡. 故障现象 安装ubuntu 16.4之后,屏幕出现闪烁现象. 重启后,进入bios,屏幕依然在闪烁. 再重启,进入另一块硬盘的win ...