Java多线程入门
一、基本概念
程序:指令和数据的有序集合。注:静态概念。
进程(Process):进程是一个具有一定独立功能的程序关于某个数据集合的一次运行活动。它是操作系统动态执行的基本单元。注:动态概念。
线程(Thread):是操作系统能够进行运算调度的最小单位(不可再分)。它被包含在进程之中,是进程中的实际运作单位,是CPU调度和执行的单位,一个进程中可以并发多个线程,每条线程并行执行不同的任务。
举个例子:
程序就像一个准备施工的工地(静态),进程就像一个正在施工的工地(动态),有自己的工地范围(内存),工人和建筑材料(指令,数据集合),可以分配不同的工人分类进行不同的施工作业(线程),实现整体的施工,有的是拌水泥,有的搬砖,有的打地基……一个工地(进程)可以包含多个施工作业(线程),不同的施工作业同时工作(多线程),最终工地建成交付(程序结束)。
为什么研究线程?
因为虽然支持多线程,但CPU调度线程执行是逐个调度的,需要进行并发控制,例如工地上搬砖的(线程A),拌水泥的(线程B)在同时工作,但只有一辆卡车(CPU),卡车不能一边去装水泥一边装砖头,所以需要并发控制(比如设置线程优先级),保证线程安全。
二、创建线程的方式
1.继承Thread类
创建一个类继承Thread类,重写父类中的run()方法,在需要使用时,实例化该对象,调用start()方法,创建一个新线程并自动执行run()方法。
/**
* 线程创建方法1:继承Thread类
*/
public class TestThread1 extends Thread{
// 重写父类中run()方法
@Override
public void run() {
// 新线程循环
for(int i=0;i<20;i++){
System.out.println("这是新线程第"+i+"次循环");
}
}
// 主线程
public static void main(String[] args){
// 创建类实例
TestThread1 testThread1 = new TestThread1();
// start()方法开启新线程,并执行run()方法
testThread1.start();
// 主线程循环
for(int i=0;i<1000;i++){
System.out.println("这是主线程第"+i+"次循环");
}
}
}
2.实现Runnable接口
创建一个类实现Runnable接口,将该类对象传入Thread类的构造器,创建一个Thread对象,调用start()方法,创建一个新线程并自动执行run()方法。
/**
* 线程创建方法2:实现Runnable接口
*/
public class TestThread2 implements Runnable{
// 实现接口中run()方法
@Override
public void run() {
// 新线程循环
for(int i=0;i<20;i++){
System.out.println("这是新线程第"+i+"次循环");
}
}
// 主线程
public static void main(String[] args){
// 创建类实例
TestThread2 testThread2 = new TestThread2();
// 传入Thread构造器,创建Thred实例,并执行start()方法
new Thread(testThread2).start();
// 主线程循环
for(int i=0;i<1000;i++){
System.out.println("这是主线程第"+i+"次循环");
}
}
}
三、线程并发问题
以抢票为例,模拟多线程中可能出现的问题,设置ticketNum为总票数,创建三个名为“张三”,“李四”,“钱五”的线程模拟三名抢票人。当线程并发时,在同一时间抢票,可能抢到的是同一张票,而正常情况下一张票不能卖给多人。
/**
* 线程并发产生的问题实例
* 抢票问题
*/
public class Thread3 implements Runnable{
// 设置总票数为10
private int ticketNum = 10;
@Override
public void run() {
// 执行抢票操作,直到票售空
while(true){
if(ticketNum<=0){
System.out.println("票没有了"+Thread.currentThread().getName()+"回家了");
break;
}
// 每抢一张,票减少一张
try{
// 设置延迟,不然运行太快,很容易一个线程把票抢光了
Thread.sleep(200);
}catch(InterruptedException e){
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"抢到了第"+ticketNum--+"张票");
}
}
public static void main(String[] args){
Thread3 thread3 = new Thread3();
// 三个线程模拟三个抢票人,开始抢票
new Thread(thread3,"张三").start();
new Thread(thread3,"李四").start();
new Thread(thread3,"钱五").start();
}
}
此例子中,出现了三个人买到同一张票的问题,甚至票售空时,还有人能买到票,这违背了正常的思维逻辑,如果生活中银行系统出现这样的现象,将造成巨大的财务漏洞,计算机内存出现这样的现象,将造成内存泄漏甚至系统崩溃的问题,所以不可忽视。
本文地址:https://blog.csdn.net/The_3/article/details/110947923
上一篇: QueryRunner常用方法
下一篇: AngularJS中的表单简单入门