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 ...
随机推荐
- 用java实现删除文件夹里的所有文件
package com.org.improve.contact; import java.io.File; public class DeletePaper { /** * @param args * ...
- 如何使用rem单位
最近搞移动端,真是被rem.em与px的换算要了老命了,看了不少文档,似乎弄明白了,这不今天用又蒙圈了. 好多文档上老是说用rem就给html设置font-size,用em就给body设置font-s ...
- FormCollection的用法
FormCollection的用法: 有时候前台抛来的字段太多,在后台一个一个例举出来显得麻烦,而且还容易出错,FormCollection解决了这个烦恼 #region 给商家留言 [HttpPos ...
- Axis Java调C# Webservice
这是一个痛苦的过程,如果java对java的webservice可以说很方便,很简单,Axis,CXF等一系列框架生成客户端直接传参调用即可,但是异构语言就有点麻烦了,生成的客户端不好使......无 ...
- ORACLE:毫秒与日期的相互转换,获取某天的信息
毫秒转换为日期 SELECT TO_CHAR(1406538765000 / (1000 * 60 * 60 * 24) + TO_DATE('1970-01-01 08:00:00', 'YYYY- ...
- SQLServer:执行计划
http://www.cnblogs.com/kissdodog/category/532309.html
- vos设置可呼出手机或固话
问题: 默认公司只让呼出手机号码,但有的客户要求能打固话,怎么办? 落地网关——补充设置——落地前缀——落地被叫改写规则 在改写规则里添加固话号段即可 具体案例: 5201——1表示让520号段只能拨 ...
- 洛谷 P2251 质量检测
题目背景 无 题目描述 为了检测生产流水线上总共N件产品的质量,我们首先给每一件产品打一个分数A表示其品质,然后统计前M件产品中质量最差的产品的分值Q[m] = min{A1, A2, ... Am} ...
- 【2017-07-04】Qt信号与槽深入理解之一:信号与槽的连接方式
今天是个好日子,嗯. 信号槽机制是Qt的特色功能之一,类似于windows中的消息机制,在不同的类对象间传递消息时我们经常使用信号槽机制,然而很多时候都没有去关注connect()函数到底有几种重载的 ...
- 【BZOJ1067】[SCOI2007] 降雨量(RMQ+分类讨论)
点此看题面 大致题意:请你判断"\(x\)年是自\(y\)年以来降雨量最多的"这句话的真假. 离散化/\(lower\_bound\) 首先,考虑到年份的范围非常大,便可以离散化. ...