多线程 用java实现线程程序
继承Thread
重写父类run方法
创建子类对象
子类对象调用start方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 package day14;public class Test02 { public static void main (String[] args) { SubThread subThread = new SubThread(); subThread.start(); for (int x=0 ;x<100 ;x++){ System.out.println("main.." +x); } } } class SubThread extends Thread { @Override public void run () { for (int x=0 ;x<100 ;x++){ System.out.println("x.." +x); } } }
实现线程程序中的问题
线程内存图 方法栈
当线程对象执行start后,jvm中会出现一个新的方法栈,run方法进栈
CPU将自动从新的栈内存中读取方法执行
线程中的名字
在run中使用super.getName()和super.setName()来获取和设置线程的名字
1 2 3 4 5 6 7 8 9 10 11 12 13 public class Test03 { public static void main (String[] args) { SubThread1 subThread1 = new SubThread1(); subThread1.start(); } } class SubThread1 extends Thread { @Override public void run () { System.out.println("线程名字:" +super .getName()); } }
1 2 3 4 5 public static void main (String[] args) { Thread thread = Thread.currentThread(); System.out.println(thread.getName()); }
设置线程优先级
线程对象.setPriority() 写在start()之前
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 public class Test03 { public static void main (String[] args) { SubThread1 subThread0 = new SubThread1(); subThread0.setPriority(Thread.MIN_PRIORITY); subThread0.start(); SubThread1 subThread1 = new SubThread1(); subThread1.setPriority(Thread.MAX_PRIORITY); subThread1.start(); } } class SubThread0 extends Thread { @Override public void run () { for (int i = 0 ; i < 100 ; i++) { Thread thread = Thread.currentThread(); System.out.println(thread.getName()); } } } class SubThread1 extends Thread { @Override public void run () { for (int i = 0 ; i < 100 ; i++) { Thread thread = Thread.currentThread(); System.out.println(thread.getName()); } } }
线程对象的方法join()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 package day14;public class Test04 { public static void main (String[] args) throws InterruptedException { SubThread3 subThread1 = new SubThread3(); subThread1.start(); SubThread3 subThread2 = new SubThread3(); subThread2.start(); } } class SubThread3 extends Thread { @Override public void run () { for (int i = 0 ; i < 100 ; i++) { Thread thread = Thread.currentThread(); Thread.yield(); System.out.println(thread.getName()); } } }
实现线程程序接口实现
定义类实现接口Runnable接口
重写接口的抽象方法run()
创建Thread类的对象,构造方法传递Runnalbe接口实现类的对象
调用Thread类的方法start()启动线程
接口实现类
1 2 3 4 5 6 7 8 public class SubRunnable implements Runnable { @Override public void run () { for (int i = 0 ; i < 100 ; i++) { System.out.println(i); } } }
运行
1 2 3 4 5 6 7 8 9 public class Test { public static void main (String[] args) { Runnable subRunnable = new SubRunnable(); Thread thread = new Thread(subRunnable); thread.start(); } }
使用匿名内部类的形式创建线程 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 public class Test { public static void main (String[] args) { new Thread(){ @Override public void run () { System.out.println("线程启动...继承Thread实现" ); } }.start(); new Thread( new Runnable(){ @Override public void run () { System.out.println("线程启动...接口实现" ); } }).start(); } }
线程安全问题 线程安全问题出现的前提:多个线程同时操作一个共享的资源
100张火车票,3个窗口。售票问题,存在安全隐患。有可能会出现,也可能不出现。
1 2 3 4 5 6 7 8 9 10 11 12 public class Windows implements Runnable { private int ticket=100 ; @Override public void run () { while (true ){ if (ticket>0 ){ System.out.println("出售第" +ticket--+"张" +"---" +Thread.currentThread().getName()); } } } }
1 2 3 4 5 6 7 8 9 10 11 12 13 public class Test { public static void main (String[] args) { Windows windows = new Windows(); Thread thread0 = new Thread(windows); Thread thread1 = new Thread(windows); Thread thread2 = new Thread(windows); thread0.start(); thread1.start(); thread2.start(); } }
解决办法:一个线程没有执行完售票,其他线程不能执行。
使用synchronized(任意对象){}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 public class Windows implements Runnable { private int ticket=100 ; private Object obj=new Object(); @Override public void run () { while (true ){ synchronized (obj){ if (ticket>0 ){ try { Thread.sleep(5 ); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("出售第" +ticket--+"张" +"---" +Thread.currentThread().getName()); } } } } }
同步代码块中写了一个对象,成为对象监视器,简单称为对象锁。保证线程的安全,依靠同步中的对象所在,有锁的线程进入执行,无锁的线程等待在同步代码块的外面。
同步方法 当一个方法中都是共享资源的时候,使用同步方法。否则浪费资源
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 public class Windows implements Runnable { private int ticket=100 ; private Object obj=new Object(); @Override public void run () { while (true ){ sell(); } } private synchronized void sell () { if (ticket>0 ){ try { Thread.sleep(5 ); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("出售第" +ticket--+"张" +"---" +Thread.currentThread().getName()); } } }
死锁案例 死锁案例的关键:在于多个线程同时争夺一个锁资源,造成程序假死现象。出现在同步代码块的嵌套中。
1 2 3 public class LockA { public static final LockA lockA=new LockA(); }
1 2 3 public class LockB { public static final LockB lockB=new LockB(); }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 public class DeadLock implements Runnable { private boolean flag; public DeadLock (boolean flag) { this .flag=flag; } @Override public void run () { while (true ){ if (flag){ synchronized (LockA.lockA){ System.out.println("if..lockA" ); synchronized (LockB.lockB){ System.out.println("if..lockB" ); } } }else { synchronized (LockB.lockB){ System.out.println("else..LockB" ); synchronized (LockA.lockA){ System.out.println("else..LockA" ); } } } } } }
1 2 3 4 5 6 7 8 9 10 public class Test { public static void main (String[] args) { DeadLock deadLock0 = new DeadLock(true ); DeadLock deadLock1 = new DeadLock(false ); Thread thread0 = new Thread(deadLock0); Thread thread1 = new Thread(deadLock1); thread0.start(); thread1.start(); } }
jdk5新特性Lock接口
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;public class Windows implements Runnable { private int ticket=100 ; Lock lock=new ReentrantLock(); @Override public void run () { while (true ){ sell(); } } private void sell () { lock.lock(); try { if (ticket>0 ){ Thread.sleep(5 ); System.out.println("出售第" +ticket--+"张" +"---" +Thread.currentThread().getName()); } }catch (InterruptedException e){ e.printStackTrace(); }finally { lock.unlock(); } } }