多线程的作用
没有多线程的情况:java程序会从上至下一行一行执行。解决不了同时操作的问题。比如要求写一个播放音乐的同时还可以打游戏的程序,单线程是解决不了的。
多线程可以让程序同时做多件事情,可以提高程序运行的效率。
多线程相关的基础概念
并行与并发
并行:指两个或多个事件在同一时刻发生
并发:指两个或多个事件在同一时间段内发生
线程与进程
进程:在使用任务管理器的时候,我们可以看到计算机当前正在运行的进程数量。
每一个进程代表了一个正在运行的应用程序,他们拥有独立的内存空间。
线程:线程是进程中的一个执行单元,负责当前进程中程序的执行,一个进程中至少有一个线程。
一个进程可以拥有多个线程,但是一个进程中的多个线程的内存空间是共享的。
简而言之:一个程序运行后至少有一个进程,一个进程中可以包含多个线程。
同步与异步
同步与异步指的是在使用多线程访问同一资源的时候,为了保证资源中的数据不会出现错误(资源安全性)而引入的概念。
同步:排队执行,效率低但是安全
异步:同时执行,效率高但是数据不安全
实现多线程的两种常用方式
继承Thread类
使用步骤 ⑴继承Thread类,代码如下
public class ThreadTest extends Thread {
}
继承Thread之后需要重写Thread的run()方法,并且要将完成线程真正功能的代码放在run()方法中。使用的时候调用Thread类中的start()方法执行线程。run()方法的语法格式如下:
public void run(){
/**这里写入实现功能的代码
*/
}
实例------使用两个线程实现同时输出
public class Demo01 extends Thread {
public static void main(String[] args){
new Demo01().start();
new Demo02().start();
}
@Override
public void run() {
for (int i = 0;i < 10;i++) {
System.out.println("线程1第"+i+"次输出");
}
}
public static class Demo02 extends Thread{
@Override
public void run() {
for (int i = 0;i < 10;i++) {
System.out.println("线程2第"+i+"次输出");
}
}
}
}
输出结果如下:
线程2第0次输出
线程1第0次输出
线程2第1次输出
线程1第1次输出
线程2第2次输出
线程1第2次输出
线程2第3次输出
线程1第3次输出
线程2第4次输出
线程1第4次输出
线程2第5次输出
线程1第5次输出
线程2第6次输出
线程1第6次输出
线程2第7次输出
线程1第7次输出
线程2第8次输出
线程1第8次输出
线程2第9次输出
线程1第9次输出
实现Runnable接口
实现Runnable接口的程序会创建一个Thread对象,并将Runnable对象与Thread对象相关联。
使用方法:. 定义Runnable接口的实现类,并重写该接口的run()方法
public class MyRunnable implements Runnable{
@Override
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName()+" "+i);
}
}
}
public class Demo02 {
public static void main(String[] args) {
//创建自定义类对象 线程任务对象
MyRunnable mr = new MyRunnable();
//创建线程对象
Thread t = new Thread(mr, "abc");
t.start();
for (int i = 0; i < 5; i++) {
System.out.println("xyz " + i);
}
}
}
xyz 0
xyz 1
xyz 2
xyz 3
xyz 4
abc 0
abc 1
abc 2
abc 3
abc 4
实现Runnable 与继承 Thread相比有以下优势:
通过创建任务,然后给线程分配的方式来实现多线程,更适合多个线程同时执行相同任务的情况
可以避免单继承带来得我局限性(java只允许单继承,可以多现实)
任务与线程是分离的,提高程序的健壮性
线程池技术中,接收Runnable类型的任务,不接收Thread类型的任务
Thread类中常用方法
方法 | 作用 |
---|---|
getName() | 返回此线程的名称 |
getId() | 返回此Thread的标识符 |
getPriority() | 返回此线程的优先级 |
setPriority(int newPriority) | 设置此线程的优先级 |
start() | 此线程开始执行此线程 |
sleep(long millis) | 使此线程休眠 |
setDaemon(boolean on) | 是否将此线程设置为守护线程 |
currentThread() | 获取当前正在执行的线程对象 |