目录:
1、线程基础教程
2、锁的案例:银行取现-特别版
3、死锁案例
====== ====== ======1、基础教程====== ===== =======
/**
* 程序是静态的数据 进程是动态的程序 线程是进程中的一个连续的控制流
* 程序:Code+Data
* 进程:程序+CPU
* 线程:创建+就绪+运行+阻塞+销毁
*
* 2种生成线程类的方法
* 继承:java.lang.Thread+对象.start();
* 实现:java.lang.Runnable+借助Thread类对象.start();
* 2种方式都要重写run()
*
* 常用方法
* sleep(long time);
* 主动休眠 yield();
* 主动让出CPU join(); 立即进入执行状态
* getName();setName();isAlive();currentThread();
*
* 线程的优先级:1-10 默认5 10最高
*
* 线程的同步 多个线程访问(操作)同一个资源,即发生了并发现象 为了确保共享资源合理有序的利用,而创建了同步机制
* 实现同步:通过主要关键字synchronize和wait、notify等的配合
* wait():让当前线程对象进入等待状态
* notify():让当前线程对象发出一个唤醒信号,让等待者醒来
*
*/
class Student extends Thread {
private int score;
@Override
public synchronized void run() {
try {
System.out.println(this.getName() + "开始考试...");
Thread.sleep(3000);
System.out.println("考试结束,开始阅卷");
Thread.sleep(3000);
score = (int) (Math.random() * 101);
System.out.println("阅卷结束,现在可以查询成绩了");
this.notify();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public synchronized int getScore() {
System.out.println(Thread.currentThread().getName() + "正在考试和阅卷,请稍等");
try {
this.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return score;
}
}
public class ThreadTest {
public static void main(String[] args) {
Student student = new Student();
System.out.println("同学你考试能考多少分?");
System.out.println("给我点时间,我去考试,看看");
student.start();
System.out.println("查询学生考试成绩:" + student.getScore());
}
}
====== ====== ======1、锁的案例:银行取钱====== ===== =======
package com.j2se.d511; /** * 测试同步问题 * * @author Administrator * */ public class Bank { public static void main(String[] args) { Account a1 = new Account(100, "高"); Drawing draw1 = new Drawing(80, a1); Drawing draw2 = new Drawing(80, a1); draw1.start(); // 你取钱 draw2.start(); // 你老婆取钱 } } /* * 简单表示银行账户 */ class Account { int money; String aname; public Account(int money, String aname) { super(); this.money = money; this.aname = aname; } } /** * 模拟提款操作 * * @author Administrator * */ class Drawing extends Thread { int drawingNum; // 取多少钱 Account account; // 要取钱的账户 int expenseTotal; // 总共取的钱数 public Drawing(int drawingNum, Account account) { super(); this.drawingNum = drawingNum; this.account = account; } @Override public void run() { draw(); } void draw() { synchronized (account) { if (account.money - drawingNum < 0) { return; } try { Thread.sleep(1000); // 判断完后阻塞。其他线程开始运行。 } catch (InterruptedException e) { e.printStackTrace(); } account.money -= drawingNum; expenseTotal += drawingNum; } System.out.println(this.getName() + "--账户余额:" + account.money); System.out.println(this.getName() + "--总共取了:" + expenseTotal); } }
============3、死锁案例============
class Lipstick {
}
class Mirror {
}
class Makeup extends Thread {
int flag;
String girl;
static Lipstick lipstick = new Lipstick();
static Mirror mirror = new Mirror();
@Override
public void run() {
// TODO Auto-generated method stub
doMakeup();
}
void doMakeup() {
if (flag == 0) {
synchronized (lipstick) {
System.out.println(girl + "拿着口红!");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (mirror) {
System.out.println(girl + "拿着镜子!");
}
}
} else {
synchronized (mirror) {
System.out.println(girl + "拿着镜子!");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (lipstick) {
System.out.println(girl + "拿着口红!");
}
}
}
}
}
class TestDeadLock {
public static void main(String[] args) {
Makeup m1 = new Makeup();
m1.girl = "大丫";
m1.flag = 0;
Makeup m2 = new Makeup();
m2.girl = "小丫";
m2.flag = 1;
m1.start();
m2.start();
}
// 如何解决死锁问题:
// 1. 往往是程序逻辑的问题。需要修改程序逻辑。
// 2. 尽量不要同时持有两个对象锁。如修改成如下:
void doMakeup() {
if (flag == 0) {
synchronized (lipstick) {
System.out.println(girl + "拿着口红!");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
synchronized (mirror) {
System.out.println(girl + "拿着镜子!");
}
} else {
synchronized (mirror) {
System.out.println(girl + "拿着镜子!");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
synchronized (lipstick) {
System.out.println(girl + "拿着口红!");
}
}
}
}
/*
* 同步是一种解决问题的思路,结合前面卫生间的示例,互斥方式解决多线程的原理是, 当一个人进入到卫生间内部时,别的人只能在外部时刻等待,
* 这样就相当于别的人虽然没有事情做,但是还是要占用别的人的时间, 浪费系统的执行资源。而同步解决问题的原理是,如果一个人进入到卫生间内部时,
* 则别的人可以去睡觉,不占用系统资源,而当这个人从卫生间出来以后, 把这个睡觉的人叫醒[就是wait,notify的应用。],则它就可以使用临界资源了。
* 所以使用同步的思路解决多线程问题更 加有效,更加节约系统的资源。
*/