(一道面试题)关于线程
一.多线程的主要优点:提高效率 。但是存在线程安全,上代码:
现实多线程的方法:实现Runnable接口,继承Thread类
(一般是实现Runnable接口,主要原因是java不支持多重继承,一旦你继承了Thread类那么你就无法继承其他类,局限性太大了)
一.多线程的实现
1.这里我是实现Runnable接口来实现多线程
public class Producter implements Runnable { public static List<String> nlist=new LinkedList<String>();//存放产品 private Integer number; //用来存放产品编号 private String productName; //用来存放产品名称 /* * 实现Runnable接口,生产产品,并将其添加到容器中 */ @Override public void run() { //定义产品编号,从1开始 number=nlist.size()+1; //定义产品的名字 productName=number+"号产品"; //将生产好的产品存放到容器中 nlist.add(productName); // TODO Auto-generated method stub } }
2.测试类,定义100个线程来测试多线程时发生的问题
public class TestDemo { public static void main(String[] args) throws InterruptedException { //生产100个产品 for(int i=0;i<100;i++){ Thread thread=new Thread(new Producter()); thread.start(); } //等待3s因为主线程跟线程是并行进行的.不等待返回的nlist的值不确定. Thread.sleep(3000); //遍历打印出的容器的产品 for(String s:Producter.nlist) { System.out.println(s); } } }
3.实验结果:
4.分析结果:
这是因为有多个线程同时访问了run()方法.造成了一个产品被多次制造。
二.多线程安全问题的解决:加锁(synchronized关键字)
给run()方法加锁.----目的: 当对象访问run()时只允许最多一个线程访问.这个就可以解决一个产品被多次制造的问题了.
1.修改Producter方法
public class Producter implements Runnable { public static List<String> nlist=new LinkedList<String>();//存放产品 private Integer number; //用来存放产品编号 private String productName; //用来存放产品名称 /* * 实现Runnable接口,生产产品,并将其添加到容器中 */ @Override public void run() { //加锁最多允许一个线程进来 synchronized (this.getClass()) { //定义产品编号,从1开始 number=nlist.size()+1; //定义产品的名字 productName=number+"号产品"; //将生产好的产品存放到容器中 nlist.add(productName); // TODO Auto-generated method stub } } }
2.为了容易观看修改了测试类代码(每打印10个换行):
public class TestDemo { private static int count=0; public static void main(String[] args) throws InterruptedException { //生产100个产品 for(int i=0;i<100;i++){ Thread thread=new Thread(new Producter()); thread.start(); } //等待3s因为主线程跟线程是并行进行的.不等待返回的nlist的值不确定. Thread.sleep(3000); //遍历打印出的容器的产品 for(String s:Producter.nlist) { //每10次换行 count++; System.out.print(s); if(count%10==0) { System.out.println(); } } } }
3.实验结果(没有一个重复的):
4.总结
在实现多线程时必须考虑到线程安全问题,不然会有许多的意外结果(BUG)~