线程:又称轻量级进程(Light Weight Process)。
- 程序中的一个顺序控制流程,同时也是CPU的基本调度单位。
- 进程由多个线程组成,彼此间完成不同的工作,交替执行,称为多线程。
比如:
- QQ是一个进程,当中的多个聊天窗口即是多个线程。
- Java虚拟机是一个进程,默认包含主线程(main),通过代码创建多个独立线程,与main并发执行。
线程,轻量级进程。
- 进程是操作系统资源分配的的基本单位。而线程是CPU 的基本调度单位。
- 每次运行一个应用程序都必须至少有一个进程。
- 每个进程可以拥有多个线程,但是必须,至少要有一个线程。
线程的组成部分:
- 每个线程都必须拥有CPU时间片,这是操作系统为每个线程分配的执行时间。
- 运行内存:
- 堆空间:存放线程需要使用的对象,多个线程都可以使用堆空间的对象,堆空间的对象在 后续的使用可能会引发线程安全的问题。
- 栈空间:存储线程需要使用的局部变量,每个线程都有独立的栈。
- 线程的逻辑代码。
线程的创建
- 继承Thread 类
- 编写类,继承Thread类
- 重写 run 方法
- 创建线程对象
- 调用 start 方法启动线程
以下是 继承Thread类的一个例子:
MyThread1 类
public class MyThread1 extends Thread {
@Override
public void run() {
for (int i = 0; i < 50; i++) {
System.out.println("MyThread1\t"+i);
}
}
}
MyThread2 类
public class MyThread2 extends Thread {
@Override
public void run() {
for (int i = 0; i < 50; i++) {
System.out.println("MyThread2\t" + i);
}
}
}
测试类
public class TestThread {
public static void main(String[] args) { //最先执行主线程Main
MyThread1 myThread1 = new MyThread1();
MyThread2 myThread2 = new MyThread2();
//启动线程
myThread1.start();
myThread2.start();
for (int i = 0; i < 50; i++) {
System.out.println("Main\t" + i);
}
// myThread1.run(); //普通方法启用
// myThread2.run(); //普通方法启用
System.out.println("程序结束");
}
}
结果展示,只展示部分
注意:如果只是调用 run 方法的结果只是按照普通的方法调用,而不是以线程的形式进行调用。
- 实现Runnable接口
- 编写类实现 Runnable 接口、并实现 run 方法。
- 创建Runnable实现类的对象
- 创建线程对象传递类对象
- 调用start方法启动线程
以下是实现Runnable接口的一个例子:
MyRunnable类
public class MyRunnable implements Runnable{
@Override
public void run() {
for (int i = 1; i <= 50; i++) {
//获取线程名
String name=Thread.currentThread().getName();
System.out.println(name+"-------"+i);
}
}
}
测试类:
public class TestRunnable {
public static void main(String[] args) {
//1、创建Runnable实现类对象
MyRunnable myRunnable = new MyRunnable();
//2、创建线程对象,传递实现类对象,传递线程名
Thread thread1 = new Thread(myRunnable, "我的线程1");
Thread thread2 = new Thread(myRunnable, "我的线程2");
//3、启动线程
thread1.start();
thread2.start();
}
}
结果展示,只展示部分
以下是一个使用多线程进行卖票的例子
- 首先创建一个票的类,给予一些属性
- 创建一个集合,把票保存进去,也可以当成对票的初始化
- 编写好Runnable实现类,并重写run方法,里面是对票进行售卖的逻辑代码
- 创建Runnable实现类对象
- 创建线程对象,传递Runnable实现类对象,传递线程名
- 调用线程的start方法,进行售票
public class Ticket {
//票的号码
private int ticketNumber;
//票的名字
private String ticketName;
public String getTicketName() {
return ticketName;
}
public void setTicketName(String ticketName) {
this.ticketName = ticketName;
}
public int getTicketNumber() {
return ticketNumber;
}
public void setTicketNumber(int ticketNumber) {
this.ticketNumber = ticketNumber;
}
@Override
public String toString() {
return String.format("%5d号%10s",this.getTicketNumber(),this.getTicketName());
}
}
卖票操作类:
public class Test {
//声明集合
static List<Ticket> ticketList;
//创建随机类对象
static Random random = new Random();
public static void main(String[] args) {
//创建集合对象,分配空间
ticketList = new ArrayList();
int number;
String name;
Ticket ticket;
for (int i = 1; i <= 100; i++) {
number = 1000 + i;
name = "王者峡谷系列";
//创建票对象
ticket = new Ticket();
//对票的属性进行赋值
ticket.setTicketNumber(number);
ticket.setTicketName(name);
//把票对象存储于集合中
ticketList.add(ticket);
}
//创建Runnable实现类的对象
SellingTickets sellingTickets = new SellingTickets();
//创建线程对象,传递实现类对象,传递线程名
Thread thread1 = new Thread(sellingTickets, "窗口1");
Thread thread2 = new Thread(sellingTickets, "窗口2");
Thread thread3 = new Thread(sellingTickets, "窗口3");
Thread thread4 = new Thread(sellingTickets, "窗口4");
//启动线程,进行售票
thread1.start();
thread2.start();
thread3.start();
thread4.start();
}
//编写类实现Runnable接口、并实现run方法。
static class SellingTickets implements Runnable {
@Override
public void run() {
//获取线程名方法
String windowName = Thread.currentThread().getName();
//判断集合属性是否等于0,即是否卖完票,作为循环结束条件
while (ticketList.size() != 0) {
selling(windowName);
}
}
}
//统计售卖了多少票
static int i = 1;
/**
* 卖票方法
*
* @param windowName
*/
static synchronized void selling(String windowName) {
//判断集合属性是否等于0,即是否卖完票,作为是否进行卖票操作
if (ticketList.size() != 0) {
//打印卖票次数
System.out.print(i + "\t");
i++;
//生成卖票的票的号数
int randomNumber = random.nextInt(ticketList.size());
//ticketList.get(randomNumber)获取票的信息
System.out.println(windowName + "卖出了" + ticketList.get(randomNumber));
//移除查找到的票的信息
ticketList.remove(ticketList.get(randomNumber));
}
}
}
部分结果展示