Java基础教程——多线程:创建线程
多线程
进程
每一个应用程序在运行时,都会产生至少一个进程(process)。
进程是操作系统进行“资源分配和调度”的独立单位。
Windows系统的“任务管理器”可以查看系统的进程,通过Ctrl+Shift+Esc组合键可以调出“任务管理器”。
进程具有三个特征:
- 独立性:进程拥有自己独立的资源,有私有的地址空间。
- 动态性:程序是静态的指令集合,而进程是活动的指令集合,进程有其生命周期。
- 并发性:多个进程可以在同一个处理器上并发执行,互不影响。虽然同一时刻只能有一个进程执行,但是多个进程被快速轮换执行(时间片轮换算法),宏观上有同时执行的效果(同一时间段内执行)。
现代的操作系统都支持多进程并发执行。
线程
线程(Thread)是执行特定任务的最小单位,是进程的执行单元,也被称为轻量级进程(Lightweight Process)。
一个进程至少有一个线程,也可以有多个线程。所谓多线程就是指同一个进程可以同时并发处理多个任务。
线程没有系统资源,多个线程共享其所属进程的系统资源,因此多线程运行时,需要处理好资源同步问题。

总结:
- 操作系统可以同时执行多个任务,每个任务是一个进程;
- 进程可以同时执行多个任务,每个任务是一个线程。
多线程的优点
多线程就是下图这种感觉:

对计算机来说,多线程可以提高CPU的利用率。
例如:网络的数据传输速率远低于计算机的处理能力,如果是单线程程序,在下载网络资源时,CPU需要花费大量的空闲时间来等待,而多线程能够利用这些空闲时间完成其他任务。
具体来说:
|--一个浏览器可以在下载的同时打开其他网页;
|--Web服务器可以同时相应多个用户请求;
|--QQ发送文件的时候还能跟其他人继续聊天……
当前线程
Thread.currentThread():获取当前线程
.getName():获取线程名称
public class TestMainThread {
public static void main(String[] args) {
// 获得当前运行的线程
Thread tMain = Thread.currentThread();
// 线程名称,优先级,线程组
System.out.println("当前运行的线程是:" + tMain);
System.out.println("线程名称:" + tMain.getName());
}
}
当前运行的线程是:Thread[main,5,main]
线程名称:main
创建线程
方法1:继承Thread类
Thread类代表线程,所有的线程对象都是Thread类或其子类的对象。
创建线程的步骤:
- 继承Thread类
- 重写run()方法(线程执行体)
- 创建Thread类的实例对象
- 调用start()方法启动线程
可以使用setName(…)为线程设置名字,用getName()获取。
默认情况下,主线程名为main,子线程名为Thread-0、Thread-1等。
public class _11NewThread {
public static void main(String[] args) {
Thread t1 = new MyT();
t1.setName("1");
t1.start();
Thread t2 = new MyT();
t2.setName(" 2");
t2.start();
}
}
class MyT extends Thread {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("线程:" + super.getName());
}
}
}
方法2:实现Runnable接口
Runnable是个接口,实现Runnable接口的类还可以继承其它类,这是比方法1优越的地方。
- 实现Runable接口
- 重写run()方法
- 创建Runable对象
- 创建Thread对象
- 调用thread.start()方法,启动线程
实际创建的对象还是Thread实例。
public class _12NewThreadRunnable {
public static void main(String[] args) {
MyR r1 = new MyR("A");
Thread t1 = new Thread(r1);
t1.setName("XXX");
t1.start();
MyR r2 = new MyR(" B");
Thread t2 = new Thread(r2);
t2.start();
}
}
class MyR implements Runnable {
public MyR(String s) {
this.s = s;
}
private String s;
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("线程:" + s);
}
}
}
*方法3:实现Callable接口
使用Callable和FutureTask创建线程——可以获取线程的返回值。这种做法了解即可。
- 实现Callable接口的线程,需重写call()方法,有返回值
- 需要FutureTask类包装一下Callablle,该类实现了Runable接口
- 以Future对象为参数创建线程,调用start()方法启动
- 以Futrue对象.get()接收返回值
package ahjava.p06thread;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
// 实现Callable接口的线程,需重写call()方法,有返回值
// 需要FutureTask类包装一下Callablle,该类实现了Runable接口
// 以Future对象为参数创建线程,调用start()方法启动
// 以Futrue对象.get()接收返回值
public class _13NewThreadCallable {
public static void main(String[] args) {
MyCallable _Callable = new MyCallable("A");
FutureTask<String> _FutureTask = new FutureTask<>(_Callable);
Thread _Thread = new Thread(_FutureTask);
_Thread.start();
try {
// 模拟等待,此过程可看到子线程在执行
Thread.sleep(3000);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
// 接受子线程的返回值
try {
String s = _FutureTask.get();
System.out.println("子线程的返回值 = " + s);
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
}
class MyCallable implements Callable<String> {
public MyCallable(String s) {
this.s = s;
}
private String s;
@Override
public String call() throws Exception {
for (int i = 0; i < 100; i++) {
System.out.println("线程:" + s);
}
return "我是子线程,已经执行完毕";
}
}
start()和run()
调用start()是开启新线程,调用run()是普通方法调用。
方法调用是入栈操作,调用完毕则出栈。
如果直接调用run()方法,则是在原线程中进行方法调用,用的还是之原线程的栈。
调用start()才是开启一个新线程,会创建新的栈。

线程的优先级
| 最高 | 10 | Thread.MAX_PRIORITY |
| 默认 | 5 | Thread.NORM_PRIORITY |
| 最低 | 1 | Thread.MIN_PRIORITY |
演示示例:
Thread(Runnable target, String name):为线程直接命名
Thread.currentThread():获取当前线程
public class Priority线程优先级 {
// *可能不太容易看出来
public static void main(String[] args) {
MyRu r1 = new MyRu();
MyRu r2 = new MyRu();
MyRu r3 = new MyRu();
Thread t1 = new Thread(r1);
// 创建时命名
Thread t2 = new Thread(r2, " B");
Thread t3 = new Thread(r3);
t1.setName("A");
t3.setName(" C");
t1.setPriority(Thread.MAX_PRIORITY);
t3.setPriority(Thread.MIN_PRIORITY);
t1.start();
t2.start();
t3.start();
}
}
class MyRu implements Runnable {
@Override
public void run() {
String sName = Thread.currentThread().getName();
int sPri = Thread.currentThread().getPriority();
for (int i = 0; i < 100; i++) {
System.out.println("线程:" + sName + " 优先级:" + sPri);
}
}
}
多线程的运行结果是不确定的,运行结果每次不同,可能有些时候看不出不同优先级的区别。
Java基础教程——多线程:创建线程的更多相关文章
- Java学习笔记-多线程-创建线程的方式
创建线程 创建线程的方式: 继承java.lang.Thread 实现java.lang.Runnable接口 所有的线程对象都是Thead及其子类的实例 每个线程完成一定的任务,其实就是一段顺序执行 ...
- 0036 Java学习笔记-多线程-创建线程的三种方式
创建线程 创建线程的三种方式: 继承java.lang.Thread 实现java.lang.Runnable接口 实现java.util.concurrent.Callable接口 所有的线程对象都 ...
- Java基础之多线程篇(线程创建与终止、互斥、通信、本地变量)
线程创建与终止 线程创建 Thread类与Runnable接口的关系 public interface Runnable { public abstract void run(); } public ...
- Java基础学习——多线程之线程池
1.线程池介绍 线程池是一种线程使用模式.线程由于具有空闲(eg:等待返回值)和繁忙这种不同状态,当数量过多时其创建.销毁.调度等都会带来开销.线程池维护了多个线程,当分配可并发执行的任务时, ...
- 黑马程序员——JAVA基础之多线程的线程间通讯等
------- android培训.java培训.期待与您交流! ---------- 线程间通讯: 其实就是多个线程在操作同一个资源,但是动作不同. wait(); 在其他线程调用此对象的notif ...
- Java基础教程:多线程基础(2)——线程间的通信
Java基础教程:多线程基础(2)——线程间的通信 使线程间进行通信后,系统之间的交互性会更强大,在大大提高CPU利用率的同时还会使程序员对各线程任务在处理的过程中进行有效的把控与监督. 线程间的通信 ...
- Java基础教程:多线程基础——线程池
Java基础教程:多线程基础——线程池 线程池 在正常负载的情况瞎,通过为每一个请求创建一个新的线程来提供服务,从而实现更高的响应性. new Thread(runnable).start() 在生产 ...
- Java基础教程:多线程基础(4)——Lock的使用
Java基础教程:多线程基础(4)——Lock的使用 快速开始 Java 5中Lock对象的也能实现同步的效果,而且在使用上更加方便. 本节重点的2个知识点是:ReentrantLock类的使用和Re ...
- Java基础教程:多线程杂谈——双重检查锁与Volatile
Java基础教程:多线程杂谈——双重检查锁与Volatile 双重检查锁 有时候可能需要推迟一些高开销的对象初始化操作,并且只有在使用这些对象时才进行初始化.此时程序员可能会采用延迟初始化.但要正确实 ...
随机推荐
- Mybatis---05Mybatis配置文件浅析(三)
1.objectFactory:(对象工厂)MyBatis 每次创建结果对象的新实例时,它都会使用一个对象工厂(ObjectFactory)实例来完成. 默认的对象工厂需要做的仅仅是实例化目标类,要么 ...
- java关键字之super
1.在子类的构造方法的第一条语句处调用其父类的构造方法: 如果父类提供了构造方法,并且父类不拥有无参构造方法,则要求子类拥有相同结构的构造方法.即,子类构造方法的参数个数和类型必须和父类的构造方法一致 ...
- Linux 系统编程 学习:07-基于socket的网络编程2:基于 UDP 的通信
Linux 系统编程 学习:07-基于socket的网络编程2:基于 UDP 的通信 背景 上一讲我们介绍了网络编程的一些概念.socket的网络编程的有关概念 这一讲我们来看UDP 通信. 知识 U ...
- Spring中的BeanFactory与FactoryBean看这一篇就够了
前言 理解FactoryBean是非常非常有必要的,因为在Spring中FactoryBean最为典型的一个应用就是用来创建AOP的代理对象,不仅如此,而且对理解Mybatis核心源码也非常有帮助!如 ...
- python的分支语句与循环
一.分支语句 1.if else语句 语法: if 条件判断: 执行的语句块1 else : 执行语句块2 当满足条件的时候则执行语句块1 ,不满足条件就执行语句块2 注意:1.条件判断后面要加冒号& ...
- 了解JWT认证
JWT介绍 JWT的全称为Json web token,是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519).该token被设计为紧凑且安全的,特别适用于分布式站点的 ...
- solr 文档一
[在此处输入文章标题] 参考博客: http://blog.csdn.net/matthewei6/article/details/50620600 基础环境搭建 solr版本5.5.5: 一.sol ...
- 搭建面向NET Framework的CI/CD持续集成环境(一)
前言 网上大多数都是针对主流的Spring Cloud.NET Core的CI/CD方案.但是目前国内绝大部分的公司因为一些历史原因无法简单的把项目从NET Framework切换升级到NET Cor ...
- mybatis foreach collection
原文传递:https://blog.csdn.net/qq_24084925/article/details/53790287 foreach元素的属性主要有 item,index,collectio ...
- selenium之 定位以及切换frame(iframe)(转)
frame标签有frameset.frame.iframe三种,frameset跟其他普通标签没有区别,不会影响到正常的定位,而frame与iframe对selenium定位而言是一样的,seleni ...