结合上一篇同步异步,这篇理解线程操作。

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高并发之线程基本操作的更多相关文章

  1. java高并发之线程池

    Java高并发之线程池详解   线程池优势 在业务场景中, 如果一个对象创建销毁开销比较大, 那么此时建议池化对象进行管理. 例如线程, jdbc连接等等, 在高并发场景中, 如果可以复用之前销毁的对 ...

  2. 1.6 JAVA高并发之线程池

    一.JAVA高级并发 1.5JDK之后引入高级并发特性,大多数的特性在java.util.concurrent 包中,是专门用于多线程发编程的,充分利用了现代多处理器和多核心系统的功能以编写大规模并发 ...

  3. Java高并发之线程池详解

    线程池优势 在业务场景中, 如果一个对象创建销毁开销比较大, 那么此时建议池化对象进行管理. 例如线程, jdbc连接等等, 在高并发场景中, 如果可以复用之前销毁的对象, 那么系统效率将大大提升. ...

  4. Java高并发之锁优化

    本文主要讲并行优化的几种方式, 其结构如下: 锁优化 减少锁的持有时间 例如避免给整个方法加锁 public synchronized void syncMethod(){ othercode1(); ...

  5. java高并发之锁的使用以及原理浅析

    锁像synchronized同步块一样,是一种线程同步机制.让自Java 5开始,java.util.concurrent.locks包提供了另一种方式实现线程同步机制——Lock.那么问题来了既然都 ...

  6. Java高并发之无锁与Atomic源码分析

    目录 CAS原理 AtomicInteger Unsafe AtomicReference AtomicStampedReference AtomicIntegerArray AtomicIntege ...

  7. Java高并发之设计模式

    本文主要讲解几种常见并行模式, 具体目录结构如下图. 单例 单例是最常见的一种设计模式, 一般用于全局对象管理, 比如xml配置读写之类的. 一般分为懒汉式, 饿汉式. 懒汉式: 方法上加synchr ...

  8. Java高并发之同步异步

    1.概念理解: 2.同步的解决方案: 1).基于代码 synchronized 关键字 修饰普通方法:作用于当前实例加锁,进入同步代码前要获得当前实例的锁. 修饰静态方法:作用于当前类对象加锁,进入同 ...

  9. Java 高并发之魂

    前置知识 了解Java基本语法 了解多线程基本知识 知识介绍 Synchronized简介:作用.地位.不控制并发的后果 两种用法:对象锁和类锁 多线程访问同步方法的7种情况:是否是static.Sy ...

随机推荐

  1. React.js 小书 Lesson5 - React.js 基本环境安装

    作者:胡子大哈 原文链接:http://huziketang.com/books/react/lesson5 转载请注明出处,保留原文链接和作者信息. 安装 React.js React.js 单独使 ...

  2. HDU 5371——Hotaru's problem——————【manacher处理回文】

    Hotaru's problem Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) ...

  3. Day6 下(

    T1 模拟,80? #include<iostream> #include<cstring> #include<queue> #include<algorit ...

  4. [转]Linq语法一

    LINQ即语言集成查询,是.NET Framework 3.5中新增的功能.其功能类似于数据库中的SQL语句(实际上LINQ就是针对.NET Framework的SQL):提供标准的.易于学习的查询和 ...

  5. DOS常见命令

    dir: 显示一个目录中的文件和子目录 md: 创建目录 rd: 删除目录 cd: 进入指定目录 cd..: 退回到上级目录 cd\: 退回到根目录 del: 删除文件 set: 显示.设置.删除cm ...

  6. C语言的各种输入情况介绍(ACM中常用到)

    1.最简单的输入输出形式: 计算a+b的值: scanf("%d%d",&a,&b); printf("%d\n",a+b);--------- ...

  7. js获取文件上传进度

    js获取文件上传进度: <input name="file" id="FileUpload" type="file" /> &l ...

  8. 自定义滑块Vue组件

    <div class="audio"> <audio id="audio" ref="audio" src="h ...

  9. 【起航计划 027】2015 起航计划 Android APIDemo的魔鬼步伐 26 App->Preferences->Preferences from XML 偏好设置界面

    我们在前面的例子Android ApiDemo示例解析(9):App->Activity->Persistent State 介绍了可以使用Shared Preferences来存储一些状 ...

  10. hp zbook15G2 nVidia K1100M显卡在ubuntu linux下闪屏问题

    我的hp zbook15G2有一块nVidia K1100M显卡. 故障现象 安装ubuntu 16.4之后,屏幕出现闪烁现象. 重启后,进入bios,屏幕依然在闪烁. 再重启,进入另一块硬盘的win ...