java基础多线程

本文详细介绍了Java中的多线程概念,包括线程与进程的区别、JVM的多线程启动、模拟多线程的两种方式(继承Thread类和实现Runnable接口)、线程的生命周期、线程安全问题及其解决方法,以及通过卖票程序实例演示线程安全问题。最后讨论了单例模式中的懒汉式线程安全问题及其解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


多线程(理解)
(1)线程:线程是进行的执行单元,执行路径。
进程:就是正在运行的程序。一块正在被使用的内存区域。
如果一个应用程序的执行只有一条执行路径,被称为单线程程序。
如果一个应用程序的执行有多条执行路径,被称为多线程程序。
举例:
迅雷下载,360管理界面,班长请吃饭,去医院体检
(2)JVM的启动是多线程的吗?(理解)
是。因为如果JVM启动只启动了main线程的话,那么,在程序的执行过程中,
有可能会引发内存溢出,而java很少看到这种情况,为什么呢,就是因为,
java的垃圾回收线程一直也在运行,当内存不够的情况,会自动去扫描内存中
是否有垃圾存在,有就立马清除。
这样来说,最低有两个线程启动了。所以,JVM的启动是多线程的。
(3)自己如何模拟多线程程序(掌握)
A:继承Thread类
步骤:
a:创建一个类,继承Thread类
b:重写run方法
c:创建类对象,调用start方法
代码体现:
public class ThreadDemo extends Thread
{
@Override
public void run()
{
for(int x=0; x<100; x++)
{
System.out.println(getName()+"***"+x);
}
}
}
public class ThreadDemoTest
{
public static void main(String[] args)
{
ThreadDemo td1 = new ThreadDemo("刘备");
ThreadDemo td2 = new ThreadDemo("孙权");
td1.start();
td2.start();
}
}
B:实现Runnable接口
步骤:
a:创建一个类,实现Runnable接口
b:重写run方法
c:创建Thread类对象,创建Runnable子类对象,把Runnable的子类
对象作为构造参数传递给Thread的构造方法
d:调用start方法
代码体现:
public class RunnableDemo implements Runnable
{
@Override
public void run()
{
for(int x=0; x<100; x++)
{
System.out.println(Thread.currentThread().getName()+"***"+x);
}
}
}
public class ThreadDemoTest
{
public static void main(String[] args)
{
RunnableDemo rd = new RunnableDemo();
Thread td1 = new Thread(rd,"林青霞");
Thread td2 = new Thread(rd,"刘意");
td1.start();
td2.start();
}
}
(4)实现多线程的方式有几种,分别怎么实现?(参照(3))(理解)
(5)启动线程调用的是哪个方法,它做了什么事情?(理解)
启动线程调用的是start()方法。
它启动线程,并且自动调用了run()方法。
start()和run()的区别?
(6)线程的生命周期及每个状态的特点。(理解)
新建:创建线程对象
就绪:具有执行资格,没有执行权
运行:具有执行资格,有执行权
阻塞:没有执行资格,没有执行权
死亡:对象变成垃圾
建议画出图。
(7)下午通过卖票程序演示出线程安全问题。(理解)
A:线程安全是怎么产生的?
线程的随机性
线程的延迟性
B:如何判断某段代码有没有线程安全问题呢?
a:有没有共享数据
b:看是否有多条语句操作共享数据
c:看是否有多个线程进行操作
c:如何解决线程安全问题?
a:同步代码块
synchronized(对象)
{
需要被同步的代码。
}
对象:可以是任意对象。
b:同步方法
在方法上添加synchronized关键字即可
锁对象:this
注意:静态方法的锁对象 当前类的字节码文件对象。
类名.class
D:同步前提
a:两个以上的线程操作的时候
b:对这多个线程加同步必须使用的是同一把锁
E:同步弊端
每次程序的执行都会去判断锁对象,消耗了资源,降低了效率。
线程安全,效率低。
线程不安全,效率高。
开发中的一个难题:要么效率,要么安全。
(8)卖票程序(案例 写一遍)
public class Ticket implements Runnable
{
//定义100张票
private int tickets = 100;
@Override
public void run()
{
while(true)
{
synchronized(this){
if(tickets>0)
{
try{
Thread.sleep(10);
}catch(InterruptedException e){
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"正在卖出第"+(tickets--)+"张票");
}
}
}
}
}
public class Test
{
public static void main(String[] args)
{
Ticket t = new Ticket();
Thread t1 = new Thread(t,"窗口1");
Thread t2 = new Thread(t,"窗口2");
Thread t3 = new Thread(t,"窗口3");
Thread t4 = new Thread(t,"窗口4");
t1.start();
t2.start();
t3.start();
t4.start();
}
}
(9)单例设计模式的懒汉式,请问他有没有线程安全问题?有的话,怎么解决?
public class Student
{
private Student(){}
private static Student s = null;
public synchronized static Student getStudent()
{
//t1,t2,t3
if(s==null)
{
//t1,t2,t3
s = new Student();
//t1线程首先创建了一个对象
//t2线程继续创建了一个对象
//t3线程又创建了一个对象
}
return s;
}
}
A:延迟加载
B:线程安全问题

//开发中,用饿汉式即可。
public class Student
{
private Student(){}
private static Student s = new Student();
public static Student getStudent()
{
return s;
}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值