【Java】多线程初探
Java的线程状态
- getState方法:返回该线程的状态,可能是NEW, RUNNABLE, BLOCKED, WAITING, TIME_WAITING, TEMINATED之一
- getName: 返回线程名称
- getPriority: 返回线程优先级
public class MyThread extends Thread{
@Override
public void run() {
System.out.println("线程状态:" + Thread.currentThread().getState());
System.out.println("线程名称:" + Thread.currentThread().getName());
System.out.println("线程优先级:" + Thread.currentThread().getPriority());
}
public static void main (String args []) {
MyThread t = new MyThread();
t.start();
}
}
输出:
线程状态:RUNNABLE
线程名称:Thread-0
线程优先级:5
线程的创建和启动
一. 继承Thread类创建线程
public class MyThread extends Thread {
private int i = 0;
public void run () {
i++;
System.out.println(i);
}
public static void main (String args []){
MyThread t = new MyThread();
t.start();
}
}
1
二. 实现Runnable接口创建线程
public class MyRunnable implements Runnable {
private int i =0;
@Override
public void run() {
i++;
System.out.println(i);
}
}
Test.java
public class Test {
public static void main (String args[]) {
Thread t = new Thread(new MyRunnable());
t.start();
}
}
输出
1
三. 通过Callable接口和Future接口创建线程
public interface Future<V> {
V get () throws ...; // 当任务完成时, 获取结果
V get (long timeout, TimeUnit unit); // 在get方法的基础上指定了超时时间
void cancel ( boolean mayInterupt); // 取消任务的执行
boolean isDone (); // 任务是否已完成
boolean isCancel (); // 任务是否已取消
}
- 对于Callable对象来说, Future对象可帮助它保存结果信息,当调用get方法的时候将会发生阻塞, 直到结果被返回。
- 而对于Runnable对象来说, 无需保存结果信息, 所以get方法一般为null, 这里Future的作用主要是可以调用cancel方法取消Runnable任务
FutureTask task = new FutureTask(new Callable);
得到的task既是一个Runnable也是一个Future。这样一来,可以先把得到的task传入Thread构造函数中创建线程并运行(作为Runnable使用), 接着通过task.get以阻塞的方式获得返回值(作为Future使用)
import java.util.concurrent.Callable;
public class MyCallable implements Callable {
@Override
public Object call() throws Exception {
Thread.sleep(1000);
return "返回值";
}
}
Test.java
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
public class Test {
public static void main (String args []) throws ExecutionException, InterruptedException {
// task同时实现了Runnable接口和Future接口
FutureTask task = new FutureTask(new MyCallable());
// 作为 Runnable 使用
Thread t = new Thread(task);
t.start();
// 作为Future使用, 调用get方法时将阻塞直到获得返回值
System.out.println(task.get());
}
}
返回值
四.通过线程池创建和管理线程
public interface Executor {
void execute(Runnable command);
}
public interface ExecutorService extends Executor {
void shutdown();
<T> Future<T> submit(Callable<T> task);
<T> Future<T> submit(Runnable task, T result);
// 其他方法
}
- 调用submit方法可以将Runnable或Callable实例提交给线程池里的空闲线程执行,同时返回一个Future对象, 保存了和执行结果有关的信息
- 当线程池用完时, 需要调用 shutdown方法关闭线程
public class Executors {
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>());
}
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>());
}
}
public class MyRunnable implements Runnable{
@Override
public void run() {
for (int i=0;i<3;i++) {
System.out.println("MyRunnable正在运行");
}
}
}
import java.util.concurrent.Callable;
public class MyCallable implements Callable{
@Override
public Object call() throws Exception {
for (int i=0;i<3;i++) {
System.out.println("MyCallable正在运行");
}
return "回调参数";
}
}
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class Test {
public static void main (String args []) throws ExecutionException, InterruptedException {
// 创建一个固定数量为2的线程池
ExecutorService service = Executors.newFixedThreadPool(2);
// 向线程池提交Callable任务,并将结果信息保存到Future中
Future callableFuture = service.submit(new MyCallable());
// 向线程池提交Runnable任务,并将结果信息保存到Future中
Future runnableFuture = service.submit(new MyRunnable());
// 输出结果信息
System.out.printf("MyCallable, 完成:%b取消:%b返回值:%s%n", callableFuture.isDone(),
callableFuture.isCancelled(), callableFuture.get());
System.out.printf("MyRunnable, 完成:%b取消:%b返回值:%s%n", runnableFuture.isDone(),
runnableFuture.isCancelled(), runnableFuture.get());
// 关闭线程池
service.shutdown();
}
}
MyCallable正在运行
MyCallable正在运行
MyCallable正在运行
MyCallable, 完成:true取消:false返回值:回调参数
MyRunnable正在运行
MyRunnable正在运行
MyRunnable正在运行
MyRunnable, 完成:false取消:false返回值:null
线程的运行
线程的阻塞(广义)
- 阻塞(Blocked)是试图获得对象锁(不是java.util.concurrent库中的锁),而对象锁暂时被其他线程持有导致
- 等待(Waiting)则是调用Object.wait,Thread.join或Lock.lock等方法导致的
- 计时等待(Time waiting)则是在等待的方法中引入了时间参数进入的状态,例如sleep(s)
线程的终止
1. 共享变量结束线程
public class InteruptSimulation implements Runnable{
private volatile static boolean stop = false;
@Override
public void run() {
try {
while (!stop) {
System.out.println("线程正在运行");
// 休眠5秒
Thread.sleep(5000);
}
System.out.println("线程终止");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void main (String args []) throws InterruptedException {
Thread t = new Thread(new InteruptSimulation());
t.start();
// 休眠1秒
Thread.sleep(1000);
// 将共享变量stop置为true
System.out.println("发出终止线程的信号");
stop = true;
}
}
线程正在运行
发出终止线程的信号
// 约5s后输出
线程终止
2. 利用中断机制结束线程
public class InteruptReal implements Runnable{
@Override
public void run() {
try {
while (!Thread.currentThread().isInterrupted()) {
System.out.println("线程正在运行");
Thread.sleep(5000);
}
} catch (InterruptedException e) {
// 发生中断异常后,中断状态位会被置为false,这里不做任何操作
}
System.out.println("线程已中断");
} public static void main (String args []) throws InterruptedException {
Thread t = new Thread(new InteruptReal());
t.start();
// 休眠1s
Thread.sleep(1000);
System.out.println("发出终止线程的信号");
t.interrupt();
}
}
输出:
线程正在运行
发出终止线程的信号
// 立即输出
线程已中断
线程现在已经能够及时退出啦
public class InteruptReal implements Runnable{
@Override
public void run() {
try {
while (!Thread.currentThread().isInterrupted()) {
System.out.println("线程正在运行");
Thread.sleep(5000);
}
} catch (InterruptedException e) {
System.out.println("中断状态位:"+Thread.currentThread().isInterrupted());
} } public static void main (String args []) throws InterruptedException {
Thread t = new Thread(new InteruptReal());
t.start();
// 休眠1s
Thread.sleep(1000);
System.out.println("发出中断");
t.interrupt();
}
}
输出:
线程正在运行
发出中断
中断状态位:false
线程的常用方法调用
Thread.sleep
Thread.yeild
Thread.join
public class JoinRunnable implements Runnable{
@Override
public void run() {
for(int i=0;i<3;i++) {
System.out.println(Thread.currentThread().getName()+ "正在执行");
}
}
public static void main (String args[]) throws InterruptedException {
Thread t = new Thread(new JoinRunnable());
t.start();
System.out.println("子线程执行完毕");
}
}
子线程执行完毕
Thread-0正在执行
Thread-0正在执行
Thread-0正在执行
public class JoinRunnable implements Runnable{
@Override
public void run() {
for(int i=0;i<3;i++) {
System.out.println(Thread.currentThread().getName()+ "正在执行");
}
}
public static void main (String args[]) throws InterruptedException {
Thread t = new Thread(new JoinRunnable());
t.start();
t.join();
System.out.println("子线程执行完毕");
}
}
输出:
Thread-0正在执行
Thread-0正在执行
Thread-0正在执行
子线程执行完毕
【Java】多线程初探的更多相关文章
- Java多线程初探
多线程 单线程的程序只有一个顺序执行流.多个顺序流之间互不干扰. 多线程的创建 定义Thread类的子类,重写该类的run()方法. 创建Thread子类的实例. 调用线程对象的start()方法来启 ...
- java并发初探ConcurrentHashMap
java并发初探ConcurrentHashMap Doug Lea在java并发上创造了不可磨灭的功劳,ConcurrentHashMap体现这位大师的非凡能力. 1.8中ConcurrentHas ...
- java并发初探ReentrantWriteReadLock
java并发初探ReentrantWriteReadLock ReenWriteReadLock类的优秀博客 ReentrantReadWriteLock读写锁详解 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) 版权声明:本文为博主原创文章,未经博 ...
随机推荐
- radiobutton独特属性
radiobutton是通过name来分组的,也就是说,使用相同的名字的radio,它们才是单选的,如果名字不同的radio,是不具备这个效果的,这个是第一要点. 第二,针对不同的radio(name ...
- 审计日志中的AOP
审计跟踪(也称为审核日志)是一个安全相关的时间顺序记录,记录这些记录的目的是为已经影响在任何时候的详细操作,提供程序运行的证明文件记录.源或事件 MVC 自定义一个过滤器 public class A ...
- HDU 4034 Graph(Floyd变形——逆向判断)
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4034 Problem Description Everyone knows how to calcu ...
- Unity Object Pool完全体
using System; using System.Collections.Generic; using UnityEngine; using UnityEngine.Events; public ...
- 全国银行列表json格式
var list=[ { value:'CDB', text:'国家开发银行' }, { value:'ICBC', text:'中国工商银行' }, { value:'ABC', text:'中国农 ...
- css3图片动画旋转
body{ background-color:#021E36; text-align: center; } .container{margin:500px auto;} .round{position ...
- Python解析JSON详解
JSON 函数 使用 JSON 函数需要导入 json 库:import json. 函数 描述 json.dumps 将 Python 对象编码成 JSON 字符串 json.loads 将已 ...
- (1-1)SpringCloud-Eureka:服务的注册与发现
SpringCloud Eureka是SpringCloud Netflix服务套件中的一部分,它基于Netflix Eureka做了二次封装,主要负责完成微服务架构中的服务治理功能.下面来做一个示例 ...
- Python 斐波那契数列练习
# coding=gbk # 迭代法---1 def fibonacci (n): if n == 0 or n == 1: return n else : a = 0 b = 1 for i in ...
- Makefile 的使用
第一篇: OBJS = ./persion.o all : persion @echo "version 03" persion : $(OBJS) g++ -o $@ $^ ./ ...