java多线程回顾1:线程的概念与创建
1、进程与线程的概念
现在几乎所有操作系统都支持多任务,通常一个任务就是一个程序,一个运行中的程序就是一个进程。当一个程序行时,其内部也可能在执行多个任务,进程内每一个任务的执行流,就是一个线程。
所以线程也被称作轻量级进程。
总而言之,线程是进程的组成部分,可以独立、并发的执行任务。
2、线程的创建和启动
Java中有两种方式来创建和启动线程。
2.1继承Thread类创建和启动线程
通过继承Thread类创建并启动多线程的步骤如下:
1、创建Thread的子类,并重写run方法。run方法中就是线程要执行的任务,所以也把run方法称为线程执行体。
2、创建该子类的实例,即线程对象。
3、使用线程对象的start方法启动线程。
线程类代码如下:
//通过继承Thread类来创建线程类
public class ThreadOne extends Thread{
private int i;
//重写run方法,方法体就是线程要执行的任务
@Override
public void run() {
for (i = 0; i < 20; i++) {
//继承Thread类时,可以直接调用getName()方法来返回当前线程的名字
//如果想获取当前线程,直接使用this即可
System.out.println(getName()+" "+i);
}
}
}
测试代码如下:
public class TestThreadOne {
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
//打印主线线程的信息
System.out.println(Thread.currentThread().getName()+" "+i);
if (i==3) {
//创建并启动第一条线程
new ThreadOne().start();
//创建并启动第二条线程
new ThreadOne().start();
}
}
}
}
部分结果如下:
main 0
main 1
main 2
main 3
Thread-0 0
Thread-1 0
main 4
Thread-1 1
Thread-0 1
Thread-1 2
main 5
从上面的运行结果可以发现,测试类只显式的创建了两条线程,但实际上有三条线程在运行,即主线程、线程0和线程1。其中主线程的线程体是main方法里的内容。
此外,Thread-0和Thread-1两条线程输出的变量i的值是不连续的,而i并非是局部变量,而是实例成员变量,从这一点可以看出,每次创建线程都创建了一个ThreadOne对象。
2.2实现Runnable接口创建线程
实现Runnable接口创建并启动线程的步骤如下:
1、创建Runnable接口的实现类,重写run方法。run方法的内容即是线程要执行的任务。
2、创建Runnable实现类的实例,并以此实例作为Thread的target来创建Thread对象。该Thread对象才是真正的线程类。
线程类代码如下:
//通过实现Runnable接口创建线程类
public class ThreadTwo implements Runnable{
private int i;
//run方法同样是线程的执行体
@Override
public void run() {
for (i = 0; i < 5; i++) {
//实现Runnable接口创建线程类时,只能使用Thread.currentThread()来获取当前线程
System.out.println(Thread.currentThread().getName()+" "+i);
}
}
}
测试代码如下:
public class TestThreadTwo {
public static void main(String[] args) {
for (int i = 0; i < 5; i++) {
//打印主线线程的信息
System.out.println(Thread.currentThread().getName()+" "+i);
if (i==3) {
ThreadTwo threadTwo = new ThreadTwo();
//创建并启动第一条线程
new Thread(threadTwo).start();
//创建并启动第二条线程
new Thread(threadTwo).start();
}
}
}
}
运行结果如下:
main 0 main 1 main 2 main 3 Thread-0 0 Thread-1 0 main 4 Thread-1 2 Thread-0 1 Thread-0 4 Thread-1 3
从运行结果可以看出,Thread-0和Thread-1打印的i值是连续的,说明这两条线程是共享一个实例的。这是因为,我们所创建的两个Thread类使用同一个Runnable对象作为target。
在实际开发中,推荐使用实现Runnable接口的方式来创建线程,这样还可以实现或继
2.3有返回值的线程
从JDK1.5开始,java提供Callable接口和Future接口以获得线程的返回值。
Callable类似Runnable的加强版,提供一个call()方法作为线程的执行体。与Runnable的run()方法相比,call()方法更强大:
- call()方法可以有返回值
- call()可以声明抛出异常
不过Callable对象并不能直接作为Thread的target,必须使用Future对象包装一下。具体使用步骤如下:
- 创建Callable的实现类,并实现call方法,注意有泛型限制。
- 使用FutureTask包装Callable对象。
- 把FutureTask作为target传入Thread,创建启动线程。
- 调用FutureTask对象的方法获取返回值。
线程代码:
public class CallableOne implements Callable<Integer>{
@Override
public Integer call() throws Exception {
int i = 0;
for(i=0;i<10;i++){
System.out.println(Thread.currentThread().getName()+" "+i);
}
//线程返回值,模拟返回前阻塞主线程
Thread.sleep(5000);
return i;
}
}
测试代码:
public class TestCallable {
public static void main(String[] args) {
//创建Callable对象
CallableOne callableOne = new CallableOne();
//使用FutureTask包装Callable对象
FutureTask<Integer> futureTask = new FutureTask<Integer>(callableOne);
for(int i=0;i<100;i++){
System.out.println(Thread.currentThread().getName()+" "+i);
//i等于3时启动子线程,此时可见主线程与子线程交替执行
if (i==3) {
//FutureTask是Runnable的子类,可传入Thread当作target
new Thread(futureTask).start();
}
//i等于80的时候来获取子线程的返回值,此时主线程会阻塞,直到返回了结果
if (i==80) {
try {
System.out.println("线程的返回值:"+futureTask.get());
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
以上代码中,在i等于3时启动子线程,此时可见主线程与子线程交替执行。在i等于80的时候来获取子线程的返回值,此时主线程会阻塞,直到返回结果。
java多线程回顾1:线程的概念与创建的更多相关文章
- 廖雪峰Java11多线程编程-1线程的概念-2创建新线程
Java语言内置多线程支持: 一个Java程序实际上是一个JVM进程 JVM用一个主线程来执行main()方法 在main()方法中又可以启动多个线程 1.创建新线程 1.1 方法一:使用Thread ...
- java多线程总结:线程的两种创建方式及优劣比较
1.通过实现Runnable接口线程创建 (1).定义一个类实现Runnable接口,重写接口中的run()方法.在run()方法中加入具体的任务代码或处理逻辑. (2).创建Runnable接口实现 ...
- Java多线程系列--“JUC线程池”04之 线程池原理(三)
转载请注明出处:http://www.cnblogs.com/skywang12345/p/3509960.html 本章介绍线程池的生命周期.在"Java多线程系列--“基础篇”01之 基 ...
- Java多线程系列--“JUC线程池”06之 Callable和Future
概要 本章介绍线程池中的Callable和Future.Callable 和 Future 简介示例和源码分析(基于JDK1.7.0_40) 转载请注明出处:http://www.cnblogs.co ...
- Java多线程系列--“JUC线程池”02之 线程池原理(一)
概要 在上一章"Java多线程系列--“JUC线程池”01之 线程池架构"中,我们了解了线程池的架构.线程池的实现类是ThreadPoolExecutor类.本章,我们通过分析Th ...
- Java多线程系列--“JUC线程池”03之 线程池原理(二)
概要 在前面一章"Java多线程系列--“JUC线程池”02之 线程池原理(一)"中介绍了线程池的数据结构,本章会通过分析线程池的源码,对线程池进行说明.内容包括:线程池示例参考代 ...
- Java多线程系列--“JUC线程池”05之 线程池原理(四)
概要 本章介绍线程池的拒绝策略.内容包括:拒绝策略介绍拒绝策略对比和示例 转载请注明出处:http://www.cnblogs.com/skywang12345/p/3512947.html 拒绝策略 ...
- 转:java多线程CountDownLatch及线程池ThreadPoolExecutor/ExecutorService使用示例
java多线程CountDownLatch及线程池ThreadPoolExecutor/ExecutorService使用示例 1.CountDownLatch:一个同步工具类,它允许一个或多个线程一 ...
- Java多线程——进程和线程
Java多线程——进程和线程 摘要:本文主要解释在Java这门编程语言中,什么是进程,什么是线程,以及二者之间的关系. 部分内容来自以下博客: https://www.cnblogs.com/dolp ...
- Java多线程之守护线程
Java多线程之守护线程 一.前言 Java线程有两类: 用户线程:运行在前台,执行具体的任务,程序的主线程,连接网络的子线程等都是用户线程 守护线程:运行在后台,为其他前台线程服务 特点:一旦所有用 ...
随机推荐
- Java总结---继承(不断完善ing..)
java三大特性:封装.继承.多态 继承 一.目的:实现代码的复用 二.简单例子(A继承了C): public class A extends C { //检测哪些可以在子类里使用 public vo ...
- 微信小程序中事件
微信小程序中事件 一.常见的事件有 类型 触发条件 最低版本 touchstart 手指触摸动作开始 touchmove 手指触摸后移动 touchcancel 手指触摸动作被打断,如来电提醒,弹窗 ...
- HTML5远程工具
因为有从网页直接远程其他windows电脑的需求,于是通过网上搜索找到下面几个解决方案,分享一下: 1.windows的远程桌面web连接tsweb 下载地址https://www.microsoft ...
- PHP 调试时中断了事务
1.错误:Uncaught PDOException: SQLSTATE[HY000]: General error: 1205 Lock wait timeout exceeded; try res ...
- [JZOJ5781]【NOIP提高A组模拟2018.8.8】秘密通道
Description 有一副n*m的地图,有n*m块地,每块是下列四种中的一种:墙:用#表示,墙有4个面,分别是前面,后面,左面,右面.起点:用C表示,为主角的起点,是一片空地.终点:用F表示,为主 ...
- c++11::std::decltype/declval
decltype ( 实体 ) () (C++ 起) decltype ( 表达式 ) () (C++ 起) 若实参是其他类型为 T 的任何表达式,且 a) 若 表达式 的值类别为亡值,则 declt ...
- MFC连接Sqlserver
下载 ado2.h和ado2.cpp文件 在VC++ 目录-->包含目录 -->添加 msado15.dll, msjro.dll 目录. // TODO: 连接sqlserver, 在 ...
- Redis 消息队列的实现
概述 Redis实现消息队列有两种形式: 广播订阅模式:基于Redis的 Pub/Sub 机制,一旦有客户端往某个key里面 publish一个消息,所有subscribe的客户端都会触发事件 集群订 ...
- Python之文件的使用
文件概述 读写文件是最常见的IO操作.Python内置了读写文件的函数,用法和C是兼容的. 读写文件前,我们先必须了解一下,在磁盘上读写文件的功能都是由操作系统提供的,现代操作系统不允许普通的程序直接 ...
- Java NIO之Java中的IO分类
前言 前面两篇文章(Java NIO之理解I/O模型(一).Java NIO之理解I/O模型(二))介绍了,IO的机制,以及几种IO模型的内容,还有涉及到的设计模式.这次要写一些更贴近实际一些的内容了 ...