Java基础学习生疏知识点总结(19)——多线程(下)
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了Java基础学习生疏知识点总结(19)——多线程(下),小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含3751字,纯文字阅读大概需要6分钟。
内容图文
![Java基础学习生疏知识点总结(19)——多线程(下)](/upload/InfoBanner/zyjiaocheng/591/a456af6a642443a998d7d4eb46292098.jpg)
文章目录
1、线程生命周期
五种线程状态
新建:线程对象刚刚创建出来 没有start
就绪:执行start方法 启动了 没有CPU的执行权
执行:抢到了CPU的执行权 该线程在CPU上运行
阻塞:没有CPU的执行权 还缺少一些必要条件
死亡:线程中的run方法执行完,被当做垃圾被垃圾回收机制回收
各个状态之间的转换
2、多线程的实现方式二:Runnable
步骤
1.实现Runnable接口
2.重写run方法
3.创建Runnable子类对象
4.创建Thread对象,并且把刚创建的Runnable子类对象作为参数传递
5.start方法启动
public class Demo {
public static void main(String[] args) {
MyRunnable myRunnable = new MyRunnable();
// thread 对象才代表线程
Thread thread = new Thread(myRunnable);
thread.setName("宋仲基");
thread.start();
}
}
class MyRunnable implements Runnable {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName()
+"---"+i);
}
}
}
注意事项
-
我们Runnable接口子类的run()方法代码,会运行在子线程当中。
-
所以,在线程的第二种实现方式中,我们自己定义子类,实现Runnable接口的run方法,将要在子线程中执行
-
但是,Runnable子类对象,并不代表线程,它只代表,要在线程中执行的任务。
我们认为,从逻辑上说,第二种方法逻辑十分清晰:
-
线程就是一条执行路径,至于在线程这条执行路径上,究竟执行的是什么样的具体代码, 应该和线程本身没有关系的
-
也就是说,线程,和在线程(执行路径)上执行的任务应该是没有什么直接关系的
-
线程实现的第二种方式,把线程(Thread对象代表线程) 和在 线程上执行的任务(Ruannable子类对象)分开
// 为什么Runnable当中的run方法会运行在子线程当中
new Thread(Runnable target)
Thread{
private Runnable target;
init(xxx){
this.target = target;
}
run (){
if(target!=null){
target.run();
}
}
}
3、继承Thread(方式一)和实现Runnable接口(方式二)比较
方式二一 VS 方式二:
- 方式一实现步骤较方式二少
- 方式一的实现方式,存在单重继承的局限性
- 方式二将线程和任务解耦
- 方式二,便于多线程数据的共享
4、数据安全问题
练习:
多线程仿真如下场景:
假设A电影院正在上映某电影,该电影有100张电影票可供出售,现在假设有3个窗口售票。请设计程序模拟窗口售票的场景。
分析:
3个窗口售票,互不影响,同时进行。
3个窗口共同出售这100张电影票
结果:
- 产生了重复的票
- 产生了不存在的票
方式一:
public class Demo3 {
public static void main(String[] args) {
SellWindow sellWindow = new SellWindow();
SellWindow sellWindow2 = new SellWindow();
SellWindow sellWindow3 = new SellWindow();
sellWindow.setName("A窗口");
sellWindow2.setName("B窗口");
sellWindow3.setName("C窗口");
sellWindow.start();
sellWindow2.start();
sellWindow3.start();
}
}
class SellWindow extends Thread {
static int tickets = 100;
@Override
public void run() {
while (true) {
if (tickets > 0) {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(getName()+"卖了第"+tickets--+"票");
}
}
}
}
方式二:
public class Demo4 {
public static void main(String[] args) {
SellWindow2 sellWindow2 = new SellWindow2();
Thread thread = new Thread(sellWindow2);
Thread thread2 = new Thread(sellWindow2);
Thread thread3 = new Thread(sellWindow2);
thread.setName("窗口A");
thread2.setName("窗口B");
thread3.setName("窗口C");
thread.start();
thread2.start();
thread3.start();
}
}
class SellWindow2 implements Runnable {
int tickets = 100;
@Override
public void run() {
while (true) {
// 假设是线程A抢到CPU的执行权 tickets=100
// 线程B抢到了CPU的执行权 100
// 不存在的原因 假设A执行 此时 tickets=1
if (tickets > 0) {
try {
// 线程A睡眠 B睡眠
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()
+"卖了第"+tickets-- + "票");
// A走到这里 100
// 又发生了线程切换 B抢到了CPU的执行权 100
// A输出 卖了第100 张票
// B输出 卖了第100 张票
// tickets--拆成3步
// 1.取值 2.做-1操作 3.重写赋值
// ABC三个线程都进入了if
// 最坏情况
// A 卖了第1张票 此时还剩0张
// B 卖了第0张票 此时还剩-1张票
// C 卖了第-1张票 此时还剩-2张票
}
}
}
}
内容总结
以上是互联网集市为您收集整理的Java基础学习生疏知识点总结(19)——多线程(下)全部内容,希望文章能够帮你解决Java基础学习生疏知识点总结(19)——多线程(下)所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。