`

面试经-java线程安全篇

阅读更多

大家学java的人每次出去面试基本上都会遇到问一些线程、锁、阻塞等等问题,线程就会遇到各种不确定性,那么怎么解决这些问题呢?这个是个最大的问题,我按照一些从简到难整理一些思路排序一些简单的例子加上我的理解,供大家讨论一下。

一、线程创建方法

Thread,Runnable

那么问题来了,这三种方式的区别是?

1、Runnable解决了java单继承的问题,用Thread实现起来比较麻烦

2、Runnable很容易实现资源的共享

其实我们翻翻代码就能发现Thread也是impl了Runnable接口,但是最终调用都是通过start()方法调用start0()的native方法来完成新线程的创建,创建好了会直接调用方法的run(),本质上没有太大的区别。

 

二、run、start两个方法的区别  还有能直接调用.run方法吗?(有些脑残的公司可能会问这样的问题)

我解释一下,run就是普通的java method跟普通的唯一区别就是新线程启动默认调用run方法来执行,而start方法是直接调用start0来启动新线程的步骤。

 

三、synchronized关键字

这个在前面的很多文章都提到了这个关键字的使用和详解,但是这个关键字在jdk5之前地位非常之高,新版的jdk有了各种锁资源的办法这个重量级的选手渐渐地用的少了,但是地位依旧很高。

参考http://zhangzhj85.iteye.com/blog/2066401

 

 四、经典问题:有三个线程ID分别是A、B、C,请有多线编程实现,在屏幕上循环打印ABC十次既:ABCABCABC

多个线程访问共享对象或数据的方式

a.将共享数据封装到另外一个对象中,然后将这个对象逐一传递给各个runnable对象,然后线程对共享数据的操作方法也分配到哪个对象身上去完成,这样容易实现对该数据的各个操作的互斥和通信。

b.将这些runnable对象作为某一个类的内部类,共享数据作为这个外部类的成员变量,每个线程对共享数据的操作方法也分配到外部类,以便实现对共享数据进行各个操作的互斥和通信,作为内部类的runnable对象调用外部类的这些方法。

两张方法组合

 总之,要同步互斥的几段代码最好分别放在几个独立的方法中,这些方法再放到同一个类中。

 

传统实现代码

package com.cn;

public class ThreadABC {
	int i = 1;
	Object o = new Object();

	public void printA() throws InterruptedException {
		synchronized (o) {
			while (i != 1) {
				o.wait();
			}
			System.out.println("a");
			i =2;
			o.notifyAll();
		}
	}

	public void printB() throws InterruptedException {
		synchronized (o) {
			while (i != 2) {
				o.wait();
			}
			System.out.println("b");
			i =3;
			o.notifyAll();
		}
	}

	public void printC() throws InterruptedException {
		synchronized (o) {
			while (i != 3) {
				o.wait();
			}
			System.out.println("c");
			i =1;
			o.notifyAll();
		}
	}

	public static void main(String[] args) throws Exception {
		final ThreadABC threadABC = new ThreadABC();
		new Thread(new Runnable() {
			public void run()  {
				try {
					for (int i = 0; i < 10; i++)  {
						threadABC.printA();
					}
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}).start();
		
		new Thread(new Runnable() {
			public void run()  {
				try {
					for (int i = 0; i < 10; i++)  {
						threadABC.printB();
					}
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}).start();
		
		new Thread(new Runnable() {
			public void run()  {
				try {
					for (int i = 0; i < 10; i++)  {
						threadABC.printC();
					}
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}).start();
	}
}

 阻塞队列的实现

package com.cn;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

public class ThreadABC {
	int i = 1;
	Object o = new Object();
	BlockingQueue<Integer> a = new ArrayBlockingQueue<Integer>(1);
	BlockingQueue<Integer> b = new ArrayBlockingQueue<Integer>(1);
	BlockingQueue<Integer> c = new ArrayBlockingQueue<Integer>(1);
	{
		a.add(1);
	}
	public void printA() throws InterruptedException {
		a.take();
			System.out.println("a");
			b.add(1);
	}

	public void printB() throws InterruptedException {
		b.take();
		System.out.println("b");
		c.add(1);
	}

	public void printC() throws InterruptedException {
		c.take();
		System.out.println("c");
		a.add(1);
	}

	public static void main(String[] args) throws Exception {
		final ThreadABC threadABC = new ThreadABC();
		new Thread(new Runnable() {
			public void run()  {
				try {
					while (true) {
						threadABC.printA();
					}
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}).start();
		
		new Thread(new Runnable() {
			public void run()  {
				try {
					while (true) {
						threadABC.printB();
					}
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}).start();
		
		new Thread(new Runnable() {
			public void run()  {
				try {
					while (true) {
						threadABC.printC();
					}
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}).start();
	}
}

 

 

 

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics