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

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. CKEditor4.4.5 插入高度代码及上传图片

    1.首先准备所需要的插件 (1). CKEditor4.4.5  下载地址:http://ckeditor.com/download.如果不想下载直接引用CKEditor的CDN也是可以的.cdn地址 ...

  2. 修改model,映射到表中

    1. 当使用EF code first创建数据表后,数据库中会自动创建一个名为:dbo.__MigrationHistory的系统数据表, 如果尚未启用数据库迁移功能,那么每次在应用程序运行时,都会对 ...

  3. [Java][Servlet] Cannot call sendRedirect() after the response has been committed

    做一个Login Demo的时候,写了如下代码: protected void doPost(HttpServletRequest request, HttpServletResponse respo ...

  4. C#中关于静态与非静态的一个疑问

    关于静态方法.变量和非静态方法.变量的区别,园里的大神早就有了许多详细的总结,个人觉得静态方法.变量与非静态方法.变量的区别可以总结为以下两句话: 静态的是属于类的 非静态是属于对象的 就是说调用静态 ...

  5. JavaScript流程控制语句脑图

    JavaScript流程控制语句脑图 图片是从网上找来的,在这记录一下,以备后面需要的时候查找方便. JavaScript通过规定的语句让有条件的按照一定的方式执行. 分为:循环语句 while do ...

  6. sass-基础

    导入: sass的导入(@import)规则和CSS的有所不同,编译时会将@import的scss文件合并进来只生成一个CSS文件. 但是如果你在sass文件中导入css文件如@import 'res ...

  7. Quartz Cron表达式的二三事

    最近在解决产品上的一个需求,就是定期生成报告(Report),我们叫做Scheduled Report. 原理:UI获取用户输入的时间信息,后台使用Spring框架设置定时任务,这里定时任务用的就是  ...

  8. nginx启动时报错

    nginx启动时报错 原因:nginx: [emerg] mkdir() "/var/cache/nginx/client_temp" failed /var/cache/ngin ...

  9. python3绘图示例6-2(基于matplotlib,绘图流程介绍及设置等)

    #!/usr/bin/env python# -*- coding:utf-8 -*- import os import numpy as npimport matplotlib as mpltfro ...

  10. ubuntu安装rpm包,deb包等各种包

    ubuntu下的各种包的安装方法 Ubuntu麒麟自带的包管理工具有apt-get,但是里面的软件包一般年代比较久远,源更新很慢,支持也很少.如果想安装一些比较新的包,可以尝试到PPA上去找找看,找到 ...