Java oop 第13章_多线程
第13章_多线程
一、 多线程相关的概念:
- 程序:由某种编程语言开发可执行某些功能的代码组合,它是静态的概念。
- 进程:当程序被执行时的过程可以理解为讲程序从外存调入内存的过程,会为每一个程序至少开辟一个独立的内存空间,程序在内存中的状态称为一个进程。
- 线程:一个进程至少会有一个独立的内存空间,但线程是依附在进程的内存空间中工作的,因此它没有自己的独立内存空间,多个线程会共用一个进程的内存空间。
- 多线程开发:往往一个进程中可以包含多个线程,多线程开发就是要具体实施一个进程中执行(启动)多个线程。
二、 Java中如何实现多线程开发:
- 通过继承Thread类,并重写Run方法完成多线程开发。
当一个类继承Thread父类就可以通过该类调用start()方法启动线程,创建多个对象就可以启动多个线程,run()方法是在启动线程时由JVM调用执行。
代码参考:com.oop.ch13.ThreadTest
package com.oop.ch13; /**
* 练习通过继承Thread类,并重写Run()方法完成多线程开发。
*
*/
public class ThreadTest {
public static void main(String[] args) {
Person person = new Person();
person.start(); Person person1 = new Person();
person1.start(); Person person2 = new Person();
person2.start(); } } class Person extends Thread { @Override
public void run() {
Integer nums = 1;
while (true) {
if (nums <= 5) {
System.out.println(Thread.currentThread().getName() + "线程第" + nums + "次输出");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
nums++;
} else {
System.out.println("执行完成");
break;
} }
} }
- 通过实现Runnable接口,并实现Run方法完成多线程开发。
因为Java是一个单继承的编程语言,因此为了完成多线程开发,我们可能通常会直接实现Runnable接口,而不是继承Thread父类。
当一个类实现Runnable接口后,在创建Thread对象时可以将实现了Runnable的实现类对象作为参数,从而通过Thread的对象来启动多个线程。
代码参考:com.oop.ch13.RunnableTest
package com.oop.ch13;
/**
* 练习:通过实现Runnable接口,并实现Run方法完成多线程开发。
*
*/
public class RunnableTest {
public static void main(String[] args) {
Animal animal = new Animal(); //将Animal的对象作为参数传给Thread
Thread thread1 = new Thread(animal);
thread1.start(); Thread thread2 = new Thread(animal);
thread2.start(); Thread thread3 = new Thread(animal);
thread3.start();
}
} class Animal implements Runnable{
@Override
public void run() {
Integer nums = 1;
while (true) {
if (nums <= 5) {
System.out.println(Thread.currentThread().getName() + "线程第" + nums + "次输出");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
nums++;
} else {
System.out.println("执行完成");
break;
} } }
}
三、 解决多线程开发中存在的问题:
问题:在进行多线程开发时会存在线程安全的问题(同步问题),多个线程共用一个进程的内存空间,访问的变量、方法都是同一个。
解决方案:使用一个解决同步问题的关键字synchronized,具体使用方式有两种。
方式1:使用synchronized关键字修饰方法,方法就为同步方法;
方式2:使用synchronized关键字修饰一段代码块,编写一段同步代码块。
案例描述:模拟“机票销售系统”,多个窗口会销售同一个航班的票,要保证机票不能出现多个窗口销售同一张机票的情况。
代码参见:
com.oop.ch13.WindowTest
package com.oop.ch13;
/**
* 模拟“机票销售系统”,多个窗口会销售同一个航班的票,要保证机票不能出现多个窗口销售同一张机票的情况。
* 没有进行同步处理。
*
*/
public class WindowTest {
public static void main(String[] args) {
Window window = new Window(); Thread thread1 = new Thread(window);
thread1.start(); Thread thread2 = new Thread(window);
thread2.start(); Thread thread3 = new Thread(window);
thread3.start(); }
} class Window implements Runnable{ @Override
public void run() {
Integer nums = 20;
while(true) {
if (nums >0) {
System.out.println(Thread.currentThread().getName() + "销售了剩余的第" + nums + "张票");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
nums --;
}else {
System.out.println("机票销售完成");
break;
}
}
}
}
com.oop.ch13.WindowSynchronizedTest
package com.oop.ch13; /**
* 模拟“机票销售系统”,多个窗口会销售同一个航班的票,要保证机票不能出现多个窗口销售同一张机票的情况。
*
* 进行同步处理。
*
*/
public class WindowSynchronizedTest {
public static void main(String[] args) {
Windows windows = new Windows(); Thread thread1 = new Thread(windows);
thread1.start(); Thread thread2 = new Thread(windows);
thread2.start(); Thread thread3 = new Thread(windows);
thread3.start(); }
} class Windows implements Runnable { //声明为成员变量,这样多个线程共用的才是同一个变量,否则每个线程都会运行一遍run()方法
Integer nums = 20;
@Override
/*
* 用synchronized关键字修饰一段代码块
* 或用synchronized修饰方法,就是同步方法
* public void synchronized run(){}
*
*/ public void run() {
while (true) {
//同步处理
synchronized (this) {
if (nums > 0) { System.out.println(Thread.currentThread().getName() + "销售了剩余的第" + nums + "张票");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
nums--; } else {
System.out.println("机票销售完成");
break;
}
}
} }
}
四、 线程的五种状态:
1、 创建(New):
2、 就绪(Runnable):
3、 运行(Running):
4、 阻塞(Blocked):
5、 死亡(Dead):
最新文章
- SQL Sever 博客文章目录(2016-07-06更新)
- 硬件抽象层——HAL
- OpenResty 是一个全功能的 Web 应用服务器
- win10使用Composer-Setup安装Composer以及使用Composer安装Yii2最新版
- 时尚前沿:15个创意的 3D 字体设计艺术作品欣赏
- 数组添加:如何往数组的";null";位置插入数据呢?
- return *this和return this的区别
- Linux Kernel ‘write_tag_3_packet()’函数本地基于堆的缓冲区溢出漏洞
- OBIEE 简介
- <;context:annotation-config/>;
- DataPipeline | 享物说产品负责人夏凯:数据驱动的用户增长实战
- ISP PIPLINE (十四) AE(自动曝光)
- 第26月第28天 avplayer cache
- BZOJ4241 历史研究 莫队 堆
- 【shell脚本】通过遍历文件的一种批量执行shell命令的方法。
- Boosting
- BZOJ1855或洛谷2569 [SCOI2010]股票交易
- Ng第九课:神经网络的学习(Neural Networks: Learning)
- 树上三角形 BZOJ3251
- Ubuntu16.04下的英文词典Artha
热门文章
- Spring学习笔记(4)——IoC学习
- Msf+Donut执行任意可执行文件
- Codeforces 454E. Little Pony and Summer Sun Celebration
- hdu 3746 kmp的next数组理解
- promise、async、await、settimeout异步原理与执行顺序
- Java自定义注解Annotation的使用
- Vue学习笔记【10】——Vue指令之v-if和v-show
- 使用springBoot和mybatis整合时出现如下错误:org.apache.ibatis.binding.BindingException: Invalid bound statement (not found)解决方案
- go结构体上的函数
- 深入理解js——构造函数的继承