这篇文章主要是个人的学习笔记,是以例子来驱动的,加深自己对多线程的理解。
一:实现多线程的两种方法
1.继承Thread
1 class MyThread1 extends Thread{ 2 public void run(){ 3 System.out.println("这是自定义的线程"); 4 } 5 }
通过继承Thread,然后重写Thread中的run方法,把自己要实现的方法写在run()中
1 class ThreadTest1{ 2 public static void main(String[] args){ 3 MyThread1 mythread = new MyThread1(); 4 mythread.start(); 5 } 6 }
2.实现Runnable接口
1 class MyThread implements Runnable{ 2 public void run(){ 3 System.out.println("这是自定义的实现Runnable接口的线程"); 4 } 5 }
实现Runnable接口,然后实现它的方法run
1 class ThreadTest1{ 2 public static void main(String[] args){ 3 MyThread mythread = new MyThread(); 4 Thread thread = new Thread(mythread); 5 thread.start(); 6 } 7 }
把mythread传到Thread的构造方法中,然后就生成了一个线程。
二:线程的安全性问题
1 class MyThread implements Runnable{ 2 int i = 100; 3 public void run(){ 4 while(true){ 5 System.out.print(Thread.currentThread().getName()+i+“ ”); 6 Thread.yield(); 7 i--; 8 if(i<0){ 9 break; 10 } 11 } 12 } 13 }
1 class ThreadTest{ 2 public static void main(String[] args){ 3 MyThread mythread = new MyThread(); 4 Thread thread = new Thread(mythread); 5 Thread thread2 = new Thread(mythread); 6 thread.setName("线程A"); 7 thread2.setName("线程B"); 8 thread.start(); 9 thread2.start(); 10 } 11 }
ThreadTest的main运行结果:
线程A10 线程B10 线程A9 线程B8 线程A7 线程B6 线程A5 线程B4 线程A3 线程B2 线程B1 线程A0
这结果是不是很奇怪,为什么有线程A10 线程B10 。要是这是一个火车售票系统,那么不是卖个两个人同一个火车票了么?
也许这个例子过于简单,看不出什么,可以参考:http://www.blogjava.net/tscfengkui/archive/2010/11/10/337709.html?opt=admin
原因主要是线程A运行run方法,运行到System.out.println(),但是还没有运行到i--,可是这是线程B抢占到了资源,那么线程B开始运行,然后线程B又运行到了System.out.println(),然后线程A或者B中有一个运行i--.然后A再运行println()。
解决办法就是在线程运行run使用资源的时候交给他一把锁,等它把事情做完后在把锁给另一个要用这个资源的线程。这样就不会出现上述情况。 实现这个锁的功能就需要用到synchronized这个关键字。
synchronized这个关键字有两种用法1、放方法名前形成同步方法;2、放在块前构成同步块。
方法1:在方法名前形成同步方法
1 class MyThread implements Runnable{ 2 int i = 10; 3 public void run(){ 4 /* for(int i = 0; i <100; i++){ 5 //获得当前正在运行线程的名字 6 System.out.println(Thread.currentThread().getName()+i); 7 } */ 8 this.meA(); 9 } 10 public synchronized void meA(){ 11 while(true){ 12 System.out.print(Thread.currentThread().getName()+i+" "); 13 Thread.yield(); 14 i--; 15 if(i<=0){ 16 break; 17 } 18 } 19 } 20 }
运行结果
线程A10 线程A9 线程A8 线程A7 线程A6 线程A5 线程A4 线程A3 线程A2 线程A1 线程B0
方法二:放在块前构成同步块
比如上面例子中,只要在while中加入一个方法块
1 while(true){ 2 synchronized(this){ 3 System.out.print(Thread.currentThread().getName()+i+" "); 4 Thread.yield(); 5 i--; 6 if(i<0){ 7 break; 8 } 9 } 10 }
那么实现的结果和上面是一样的。
这是我今天学习多线程的结果,多线程很深奥,越学越觉得好多还不懂,只能每天进步一点。