多线程
线程
进程是应用程序的执行示例,有独立的内存空间和系统资源。
线程是CPU调度和分派的基本单位,执行运算的最小单位,可以完成独立的顺序控制流程
如果在一个进程中同时运行了多个线程,用来完成不同的工作,则称为是多线程。多个线程交替占用CPU资源,而非真正的并行执行。
- 多线程的好处
充分的利用CPU的资源,提升代码性能
简化编程模型,更好的软件设计和架构
带来良好的用户体验
Thread
java提供了java.lang.Thread类支持多线程编程,更多的信息参考java的API说明文档。
- 主线程
main()方法就是主线程入口
主线程是产生其他子线程的线程
主线程必须最后完成执行,因为它执行各种关闭动作
package Threads;
public class MainThread {
public static void main(String[] args) {
//获取当前的线程对象
Thread thread = Thread.currentThread();
//获取当前线程对象的名称
String name = thread.getName();
System.out.println("当前线程是:"+ name);
//为当前的线程重新设置名称
thread.setName("myThread");
name = thread.getName();
System.out.println("当前线程是:"+ name);
}
}
线程的创建和启动
-
在java中创建线程的第一种方式:
继承java.lang.Thread类
步骤是:
定义MyThread类继承Thread类
重写run()方法,编写线程执行体
创建线程对象,调用start()方法启动线程
package Threads;
//编写线程类
public class MyThread extends Thread {
@Override
public void run() {
for (int i = 1; i <= 100; i++) {
System.out.println(Thread.currentThread().getName() + ":" + i);
}
}
}
package Test;
import Threads.MyThread;
//测试类
public class MyThreadTest {
public static void main(String[] args) {
//创建线程对象
MyThread myThread = new MyThread();
MyThread myThread2 = new MyThread();
//启动线程
//调用start()方法是多条执行路径,主线程和子线程并行交替执行
myThread.start();
myThread2.start();
//是不是可以调用run()方法启动线程?-->不可以
//(1)只有主线程一个执行路径(2)依次调用了两次run()方法
//run()方法被当做是main()中的一个普通的方法执行,失去了线程的意义
// myThread.run();
// myThread2.run();
}
}
测试运行一下,可以看到控制台中有Thread0和Thread1交替执行输出结果。线程每次执行时长是由分配的CPU时间片长度决定的
定义线程(extends Thread 重写run()方法)–>创建线程对象(使用new创建对象)–>启动线程(调用start()方法)–>停止线程
- 在java中创建线程的第二种方式
实现Runnable接口创建线程
步骤是:
定义MyRunnable类实现Runnable接口
实现run()方法,编写线程执行体
创建线程对象,调用start()方法启动线程
package Threads;
//创建线程类,实现Runnable接口
public class MyThread2 implements Runnable {
@Override
public void run() {
for (int i = 1; i <= 100; i++) {
System.out.println(Thread.currentThread().getName() + ":" + i);
}
}
}
package Test;
import Threads.MyThread2;
//测试线程
public class MyThread2Test {
public static void main(String[] args) {
//创建线程对象
Runnable runnable = new MyThread2();
//Thread thread = new Thread(runnable);
Thread thread = new Thread(runnable,"mythread1");
Thread thread1 = new Thread(runnable,"mythread2");
//启动线程
thread.start();
thread1.start();
}
}
Thread类有两种构造方法:
Thread(Runnable target)
Thread(Runnable target,String name)
线程创建两种方式的区别
-
继承Thread类
编写简单,可以直接操作线程
适用于单继承
-
实现Runnable接口
避免单继承局限性
便于共享资源
所以推荐使用实现Runnable接口方式创建线程
如果使用继承Thread类的方式:
package Threads;
//创建线程,模拟售票的过程
public class MyThread1 extends Thread {
private int ticket = 10;
@Override
public void run() {
for (int i = 1; i <= 10; i++) {
if (this.ticket > 0) {
System.out.println(Thread.currentThread().getName() + "买票--" + this.ticket--);
}
}
}
}
package Test;
import Threads.MyThread1;
//测试线程
public class MyThread1Test {
public static void main(String[] args) {
MyThread1 thread1 = new MyThread1();
thread1.setName("窗口1");
MyThread1 thread2 = new MyThread1();
thread2.setName("窗口2");
thread1.start();
thread2.start();
}
}
测试运行一下,发现窗口1和窗口2两个线程都是从10到1,但是火车站在卖票的时候总共有10张票,如果按照实现继承Thread类的方式就不对了,因为这种方式不可以线程之间共享资源。多个线程之间分别完成自己的任务。
如果使用实现Runnable接口的方式:
package Threads;
//创建线程,模拟售票的过程
public class MyThread3 implements Runnable {
private int ticket = 10;
@Override
public void run() {
for (int i = 1; i <= 10; i++) {
if (this.ticket > 0) {
System.out.println(Thread.currentThread().getName() + "买票--" + this.ticket--);
}
}
}
}
package Test;
import Threads.MyThread3;
//测试线程
public class MyThread3Test {
public static void main(String[] args) {
Runnable runnable = new MyThread3();
Thread thread1 = new Thread(runnable, "窗口1");
Thread thread2 = new Thread(runnable, "窗口2");
thread1.start();
thread2.start();
}
}
测试运行。多个线程共同完成一份任务。
-
练习
继承Thread类
package Threads;
//编写线程类
public class MyThread4 extends Thread {
@Override
public void run() {
for (int i = 1; i <= 20; i++) {
System.out.println("您好,来自线程" + Thread.currentThread().getName() + "-" + i);
}
}
}
package Test;
import Threads.MyThread4;
//编写测试类
public class MyThread4Test {
public static void main(String[] args) {
MyThread4 t1 = new MyThread4();
MyThread4 t2 = new MyThread4();
t1.start();
t2.start();
}
}
实现Runnable接口
package Threads;
//编写线程类
public class MyThread4 implements Runnable {
@Override
public void run() {
for (int i = 1; i <= 20; i++) {
System.out.println("您好,来自线程" + Thread.currentThread().getName() + "-" + i);
}
}
}
package Test;
import Threads.MyThread4;
//编写测试类
public class MyThread4Test {
public static void main(String[] args) {
Runnable runnable = new MyThread4();
Thread t1 = new Thread(runnable);
Thread t2 = new Thread(runnable);
t1.start();
t2.start();
}
}