您的位置:首页 > 其它

多线程基础

2016-09-08 10:46 127 查看
/**

 * 创建线程两种方式: 继承Thread父类, 实现Runnable接口

 * ① 避免了java单继承的局限性

 * ② 如果多个线程要操作同一份资源(或数据), 更适合使用实现的方式

 * 

 * 线程安全问题,打印车票时,会出现重票,错票

 * 1. 线程安全问题存在的原因?

 *    由于一个线程在操作共享数据过程中,未执行完毕的情况下,另外的线程参与进来,导致共享数据存在了安全问题。

 * 2. 如何解决线程的安全问题?

 *    必须让一个线程操作共享数据完毕以后,其他线程才有机会参与共享数据的操作.

 *    方式一:同步代码块

 *     synchronized(同步监视器){

 *     需要被同步的代码块(即为操作共享数据的代码)

 *     }

 *     1. 共享数据:多个线程共同操作的同一个数据(变量)

 *     2. 同步监视器:由一个类的对象来充当。哪个线程获取此监视器,谁就执行大括号里被同步的代码块,俗称锁。

 *     要求:所有的线程必须公用同一把锁!

 *      注:在实现的方式中,考虑同步的话,可以使用 this 来充当锁。但是在继承的方式中,慎用this.

 *    方式二:同步方法

 *     将操作共享数据的方法声明为 synchronized 。即此方法为同步方法,能够保证当其中一个线程执行此方法时,

 *      其他线程在外等待直至此线程执行完此方法。

 *      >同步方法的锁:当前对象 this 。

 */

/**

* 模拟火车站售票窗口, 开启三个窗口, 总票数为 100

* 采用继承的方式实现

*/
public class TicketDemo_1 {

public static void main(String[] args) {
Object obj = new Object();
Window win1 = new Window(obj);
Window win2 = new Window(obj);
Window win3 = new Window(obj);

win1.setName("窗口1");
win2.setName("窗口2");
win3.setName("窗口3");

win1.start();
win2.start();
win3.start();
}
}

// 存在线程的安全问题 ---> 使用同步代码块处理。
class Window extends Thread {
private static int ticket = 100;
private Object obj;

public Window(Object obj) {
super();
this.obj = obj;
}

@Override
public void run() {
while(true) {
// synchronized (this) { // 在本问题中,this表示win1, win2, win3
synchronized (obj) {
if (ticket > 0) {
try {
Thread.sleep(80);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " 售票: 票号为 " + (ticket --));
} else {
break;
}
}
}
}
}

/**

* 模拟火车站售票窗口, 开启三个窗口, 总票数为 100

* 采用实现的方式+同步代码块方式实现

*/
public class TicketDemo_2 {

public static void main(String[] args) {
WindowRunnable windowRunnable = new WindowRunnable();
Thread thread_1 = new Thread(windowRunnable);
Thread thread_2 = new Thread(windowRunnable);
Thread thread_3 = new Thread(windowRunnable);

thread_1.setName("窗口1");
thread_2.setName("窗口2");
thread_3.setName("窗口3");

thread_1.start();
thread_2.start();
thread_3.start();
}
}

class WindowRunnable implements Runnable {
/**
* 多个线程共享一个对象的数据
*/
private int ticket = 100;
Object obj = new Object();

@Override
public void run() {
while(true) {
synchronized (obj) { // this就是上面的windowRunnable,只有一个对象
if (ticket > 0) {
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " 售票: 票号为 " + (ticket --));
} else {
break;
}
}
}
}
}

/**

* 模拟火车站售票窗口, 开启三个窗口, 总票数为 100

* 采用实现的方式+同步方法方式实现

*/
public class TicketDemo_3 {

public static void main(String[] args) {
WindowRunnable_1 windowRunnable = new WindowRunnable_1();
Thread thread_1 = new Thread(windowRunnable);
Thread thread_2 = new Thread(windowRunnable);
Thread thread_3 = new Thread(windowRunnable);

thread_1.setName("窗口1");
thread_2.setName("窗口2");
thread_3.setName("窗口3");

thread_1.start();
thread_2.start();
thread_3.start();
}
}

class WindowRunnable_1 implements Runnable {
/**
* 多个线程共享一个对象的数据
*/
private int ticket = 100;

@Override
public void run() {
while(true) {
if (sellTicket()) {
break;
}
}
}

private synchronized boolean sellTicket() {
if (ticket > 0) {
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " 售票: 票号为 " + (ticket --));
return false;
} else {
return true;
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: