多线程
Posted 52haiyan
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了多线程相关的知识,希望对你有一定的参考价值。
-
了解语言背景,特点.
-
语法
-
通用小程序
-
函数和对象
-
第三方类库,插件组件,框架
-
开发项目
实现多线程的两种方式:
- 继承Thread类
- 自定义MyThread继承Thread
- 在MyThread中重写run()方法
- 创建MyThread类对象
- 启动线程对象
- 实例:创建SellTicket.java和SellTicketDemo.java类
1 public class SellTicket implements Runnable { 2 //定义100张票 3 private int tickets=100; 4 //创建锁 5 private Object obj=new Object(); 6 @Override 7 public void run() { 8 synchronized(obj){ 9 while(true){ 10 if(tickets>0){ 11 try { 12 Thread.sleep(100); 13 } catch (InterruptedException e) { 14 e.printStackTrace(); 15 } 16 System.out.println(Thread.currentThread().getName()+"正在出售"+(tickets--)+"张票"); 17 } 18 } 19 } 20 } 21 }
SellTicketDemo.java类:
1 public class SellTicketDemo { 2 public static void main(String[] args) { 3 //创建资源对象 4 SellTicket st1=new SellTicket(); 5 //当前时间,在这里没有意义 6 SimpleDateFormat df = new SimpleDateFormat("EEE, MMM d, ‘‘yy"); 7 System.out.println(df.format(System.currentTimeMillis())); 8 //创建3个线程对象,传递Myrunable类的对象. 9 Thread t1=new Thread(st1, "窗口1"); 10 Thread t2=new Thread(st1,"窗口2"); 11 Thread t3=new Thread(st1,"窗口3"); 12 13 t2.start(); 14 t1.start(); 15 t3.start(); 16 } 17 }
- 实现Runable接口:
- 自定义MyRunable实现Runable接口;
- 在MyRunable里面重写run()方法;
- 创建MyRunable类的对象;
- 创建Thread类的对象,并把3中对象作为构造参数 传递.
public static void main(String[] args) { new Thread(new Thread1()).start(); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } new Thread(new Thread2()).start(); } /* * Thread1实现Runable */ private static class Thread1 implements Runnable { @Override public void run() { //由于这里的Thread1和下面的Thread2内部run方法要用同一对象作为监视器, //我们这里不能用this,因为在Thread2里面的this和这个Thread1的this不是同一个对象。我们用MultiThread.class这个字节码对象,当前虚拟机里引用这个变量时,指向的都是同一个对象。 synchronized (MultiThread.class) { System.out.println("enter thread1..."); System.out.println("thread1 is waiting"); try { //释放锁有两种方式,第一种方式是程序自然离开监视器的范围, //也就是离开了synchronized关键字管辖的代码范围, //另一种方式就是在synchronized关键字管辖的代码内部调用监视器对象的wait方法。这里,使用wait方法释放锁。 MultiThread.class.wait(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("thread1 is going on..."); System.out.println("thread1 is being over!"); } } } /* * Thread2 */ private static class Thread2 implements Runnable { @Override public void run() { synchronized (MultiThread.class) { System.out.println("enter thread2..."); System.out.println("thread2 notify other thread can release wait status.."); //由于notify方法并不释放锁, 即使thread2调用下面的sleep方法休息了10毫秒, //但thread1仍然不会执行,因为thread2没有释放锁,所以Thread1无法得不到锁。 MultiThread.class.notify(); System.out.println("thread2 is sleeping ten millisecond..."); try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("thread2 is going on..."); System.out.println("thread2 is being over!"); } } }
-
为什么要有两种方式:
- 实现Runable接口解决了java单继承的局限性,适合多个相同程序的代码去处理同一个资源的情况 ,把线程同程序代码和数据分离,较好 的体现了面向 对象的设计思想.
:
-
-
共享数据;
-
有多条语句操作数据
解决方案:就是破坏线程不安全的条件,非要在多线程下操作共享数据就只能破坏第三个条件了,把多条语句操作共享数据的代码包成一个代码块,让某个线程在执行 的时候别人不能执行,这里java给我们提供的同步机制:synchronized
1 synchronized(对象){//同步的根本就在对象,该对象如同锁,多个线程同一把锁, 2 代码块 3 }
同步的弊端 :当线程特别多时,因为每一个锁都会去判断同步上的锁,这是很浪费资源的,无形中降低了程序运行的效率.
线程安全的类有:
1 1 //线程安全的类 2 2 StringBuffer sb =new StringBuffer(); 3 3 Vector<String> v=new Vector<String>)(); 4 4 Hashtable<String,String> h=new Hashtable<String,String>();
原因:就是在这些类中实现了Runable接口,具备了线程安全的特性
使用如下代码可以使类具备线程安全:
1 //线程安全 2 List<String> li=Collections.synchronizedList(new ArrayList<String>());
以上是关于多线程的主要内容,如果未能解决你的问题,请参考以下文章