黑马程序员_java_多线程总结(下)
来源:互联网 发布:脸部比例测试软件 编辑:程序博客网 时间:2024/05/22 10:58
------- <a href="http://www.itheima.com" target="blank">android培训</a>、<a href="http://www.itheima.com" target="blank">java培训</a>、期待与您交流! ----------
(1)问题产生原理分析
注意:每个线程有个普通的成员变量Student,创建线程的时候需要先初始化该变量
(2)解决方案
1、看有没有共享数据
2、看操作共享数据的语句是不是多条语句
3、看是不是在多线程的环境中
最后,把操作共享数据的多条语句用锁 锁起来
所以给两个线程while(true){}中间的内容用加锁
修改线程1和线程2中的代码,做到必须修改完才能读取
线程1:负责修改共享数据
package tongxin;
public class SetThread extends Thread {
private Student stu;
public SetThread(Student stu) {
this.stu = stu;
}
@Override
public void run() {
int i = 0;
while (true) {
synchronized (stu) {
if (i % 2 == 0) {// 执行%2操作,是为了写入不同的数据,测试在写入过程中,是否影响另一个线程的读取操作
stu.name = "张三";
stu.age = 13;
} else {
stu.name = "李四";
stu.age = 14;
}
i++;
}
}
}
}
线程2:负责获取共享数据信息
package tongxin;
public class GetThread extends Thread {
private Student stu;
public GetThread(Student stu){
this.stu = stu;
}
@Override
public void run() {
while(true){
synchronized (stu) {
System.out.println(stu);
}
}
}
}
五、等待唤醒机制
(1)前提(掌握)
两个线程共用一把锁,此时可以调用该锁的wait和notify方法,实现等待唤醒机制
(2)IllegalMonitorStateException异常原因及解决办法
如果当前的线程不是此对象锁的所有者,缺调用该对象的notify(),notify(),wait()方法时抛出该异常
换句话说就是当前线程中的同步代码块的锁 和 调用这三个方法的锁对象不一致就会报错,例如
synchronized(Student.class){
Object.class.notify();
}
注意 必须有线程现在自食用Object.class锁
(3)sleep和wait的区别
wait:是Object类的方法,可以不用传递参数,释放锁对象
sleep:是Thread类的静态方法,需要传递参数
(4)以下代码有没有问题
public synchronized void set(String name, int age) {
if (this.flag) {
try {
Object.class.wait();
} catch (Exception e) {
}
}
this.name = name;
this.age = age;
this.flag = true;
Object.class.notify();
}
继续修改代码,做到读一次,写一次
共享数据(学生类)
package tongxin;
public class Student {
public String name;
public int age;
public boolean flag = false;
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + "]";
}
}
线程1:负责修改共享数据
package tongxin;
public class SetThread extends Thread {
private Student stu;
public SetThread(Student stu) {
this.stu = stu;
}
@Override
public void run() {
int i = 0;
while (true) {
synchronized (stu) {
if(stu.flag){
try {
stu.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if (i % 2 == 0) {// 执行%2操作,是为了写入不同的数据,测试在写入过程中,是否影响另一个线程的读取操作
stu.name = "张三";
stu.age = 13;
} else {
stu.name = "李四";
stu.age = 14;
}
i++;
stu.flag = true;
stu.notify();
}
}
}
}
线程2:负责获取共享数据信息
package tongxin;
public class GetThread extends Thread {
private Student stu;
public GetThread(Student stu){
this.stu = stu;
}
@Override
public void run() {
while(true){
synchronized (stu) {
if(!stu.flag){
try {
stu.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(stu);
stu.flag = false;
stu.notify();
}
}
}
}
测试
package tongxin;
public class Test {
public static void main(String[] args) {
//创建共享数据
Student stu = new Student();
//创建两个线程,并且让这两个线程同时操作这个共享数据
GetThread get = new GetThread(stu);
SetThread set = new SetThread(stu);
get.start();
set.start();
}
}
六、线程的优先级(Thread类中)
(1)线程优先级级别
线程默认优先级是5。范围是1-10
Thread.MAX_PRIORITY //10
Thread.MIN_PRIORITY //1
Thread.NORM_PRIORITY //5
(2)方法
public final int getPriority():获取线程优先级
public final void setPriority(int newPriority):更改线程的优先级
(3)注意
优先级可以在一定的程度上,让线程获较多的执行机会
(4)举例
MyThread t = new MyThread();
System.out.println(t.getPriority());
t.setPriority(Thread.MAX_PRIORITY);
七、暂停线程(Thread类中)
(1)概述
暂停当前正在执行的线程,让其他线程执行
(2)成员方法
public static void yield():暂停当前正在执行的线程对象,并执行其他线程。
(3)注意
是为了让线程更和谐一些的运行,但是你不要依赖这个方法保证,如果要真正的实现数据依次输出,请使用等待唤醒机制
八、加入线程(Thread类中)
(1)概念
如果调用一个线程的join方法,那么其他线程必须等待该线程执行完毕后才能执行
(2)成员方法
public final void join():等待该线程终止
线程启动后调用该方法
九、守护线程(Thread类中)
(1)成员方法
public final void setDaemon(boolean on):设置线程为守护线程,一旦前台(主线程),结束,守护线程就结束了
(2)注意
main方法就本身是一个线程,我们在main方法里创建线程,并且设置线程为守护线程后,main方法结束后,守护线程就自动结束了
(1)问题产生原理分析
注意:每个线程有个普通的成员变量Student,创建线程的时候需要先初始化该变量
(2)解决方案
1、看有没有共享数据
2、看操作共享数据的语句是不是多条语句
3、看是不是在多线程的环境中
最后,把操作共享数据的多条语句用锁 锁起来
所以给两个线程while(true){}中间的内容用加锁
修改线程1和线程2中的代码,做到必须修改完才能读取
线程1:负责修改共享数据
package tongxin;
public class SetThread extends Thread {
private Student stu;
public SetThread(Student stu) {
this.stu = stu;
}
@Override
public void run() {
int i = 0;
while (true) {
synchronized (stu) {
if (i % 2 == 0) {// 执行%2操作,是为了写入不同的数据,测试在写入过程中,是否影响另一个线程的读取操作
stu.name = "张三";
stu.age = 13;
} else {
stu.name = "李四";
stu.age = 14;
}
i++;
}
}
}
}
线程2:负责获取共享数据信息
package tongxin;
public class GetThread extends Thread {
private Student stu;
public GetThread(Student stu){
this.stu = stu;
}
@Override
public void run() {
while(true){
synchronized (stu) {
System.out.println(stu);
}
}
}
}
五、等待唤醒机制
(1)前提(掌握)
两个线程共用一把锁,此时可以调用该锁的wait和notify方法,实现等待唤醒机制
(2)IllegalMonitorStateException异常原因及解决办法
如果当前的线程不是此对象锁的所有者,缺调用该对象的notify(),notify(),wait()方法时抛出该异常
换句话说就是当前线程中的同步代码块的锁 和 调用这三个方法的锁对象不一致就会报错,例如
synchronized(Student.class){
Object.class.notify();
}
注意 必须有线程现在自食用Object.class锁
(3)sleep和wait的区别
wait:是Object类的方法,可以不用传递参数,释放锁对象
sleep:是Thread类的静态方法,需要传递参数
(4)以下代码有没有问题
public synchronized void set(String name, int age) {
if (this.flag) {
try {
Object.class.wait();
} catch (Exception e) {
}
}
this.name = name;
this.age = age;
this.flag = true;
Object.class.notify();
}
继续修改代码,做到读一次,写一次
共享数据(学生类)
package tongxin;
public class Student {
public String name;
public int age;
public boolean flag = false;
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + "]";
}
}
线程1:负责修改共享数据
package tongxin;
public class SetThread extends Thread {
private Student stu;
public SetThread(Student stu) {
this.stu = stu;
}
@Override
public void run() {
int i = 0;
while (true) {
synchronized (stu) {
if(stu.flag){
try {
stu.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if (i % 2 == 0) {// 执行%2操作,是为了写入不同的数据,测试在写入过程中,是否影响另一个线程的读取操作
stu.name = "张三";
stu.age = 13;
} else {
stu.name = "李四";
stu.age = 14;
}
i++;
stu.flag = true;
stu.notify();
}
}
}
}
线程2:负责获取共享数据信息
package tongxin;
public class GetThread extends Thread {
private Student stu;
public GetThread(Student stu){
this.stu = stu;
}
@Override
public void run() {
while(true){
synchronized (stu) {
if(!stu.flag){
try {
stu.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(stu);
stu.flag = false;
stu.notify();
}
}
}
}
测试
package tongxin;
public class Test {
public static void main(String[] args) {
//创建共享数据
Student stu = new Student();
//创建两个线程,并且让这两个线程同时操作这个共享数据
GetThread get = new GetThread(stu);
SetThread set = new SetThread(stu);
get.start();
set.start();
}
}
六、线程的优先级(Thread类中)
(1)线程优先级级别
线程默认优先级是5。范围是1-10
Thread.MAX_PRIORITY //10
Thread.MIN_PRIORITY //1
Thread.NORM_PRIORITY //5
(2)方法
public final int getPriority():获取线程优先级
public final void setPriority(int newPriority):更改线程的优先级
(3)注意
优先级可以在一定的程度上,让线程获较多的执行机会
(4)举例
MyThread t = new MyThread();
System.out.println(t.getPriority());
t.setPriority(Thread.MAX_PRIORITY);
七、暂停线程(Thread类中)
(1)概述
暂停当前正在执行的线程,让其他线程执行
(2)成员方法
public static void yield():暂停当前正在执行的线程对象,并执行其他线程。
(3)注意
是为了让线程更和谐一些的运行,但是你不要依赖这个方法保证,如果要真正的实现数据依次输出,请使用等待唤醒机制
八、加入线程(Thread类中)
(1)概念
如果调用一个线程的join方法,那么其他线程必须等待该线程执行完毕后才能执行
(2)成员方法
public final void join():等待该线程终止
线程启动后调用该方法
九、守护线程(Thread类中)
(1)成员方法
public final void setDaemon(boolean on):设置线程为守护线程,一旦前台(主线程),结束,守护线程就结束了
(2)注意
main方法就本身是一个线程,我们在main方法里创建线程,并且设置线程为守护线程后,main方法结束后,守护线程就自动结束了
0 0
- 黑马程序员_java_多线程总结(下)
- 黑马程序员_java_多线程总结(上)
- 黑马程序员_Java_多线程总结
- 黑马程序员_java_集合总结(下)
- 黑马程序员_JAVA_多线程
- 黑马程序员_Java_多线程
- 黑马程序员_java_多线程
- 黑马程序员_java_多线程
- 黑马程序员_Java_多线程
- 黑马程序员_JAVA_多线程
- 黑马程序员_Java_多线程
- 黑马程序员_Java_多线程
- 黑马程序员_Java_多线程
- **黑马程序员_Java_多线程**
- 黑马程序员_java_集合总结(上)
- 黑马程序员_java_多线程1
- 黑马程序员_java_多线程2
- 黑马程序员_Java_集合总结
- 黑马程序员_java_IO流总结(上)
- 了解Android微信里的WebView是如何实现分享的功能
- 黑马程序员_java_IO流总结(中)
- 黑马程序员_java_IO流总结(下)
- 黑马程序员_java_多线程总结(上)
- 黑马程序员_java_多线程总结(下)
- 黑马程序员_java_反射总结
- 程序员该有的艺术气质—SOLID原则
- 犀牛——第7章 7.3稀疏数组
- 黑马程序员_java_集合总结(上)
- 黑马程序员_java_集合总结(下)
- 黑马程序员_java_面向对象总结
- 数组转换(二进制-八进制-十六进制)-第6天
- HDOJ 2317 Nasty Hacks