Java 多线程总结
------- android培训、java培训、期待与您交流! ----------
多线程两种方式:
继承Thread类
定义一个子类继承Thread。复写Thread类中的run方法。调用该对像的start方法
start方法有两个作用,启动线程,调用run方法。
class Demo extends Thread { public void run() { for (int x = 0; x < 100; x++) System.out.println("demo " + x); } } class ThreadDemo1 { public static void main(String[] args) { Demo d = new Demo(); d.start(); for (int x = 0; x < 100; x++) System.out.println("main " + x); } }
实现Runnable接口
覆盖Runnable接口的run方法
通过Thread类建立线程对象
将Runnable接口的子类对象作为实际参数传递给Thread类的构造函数
调用Thread类的start方法开启线程并调用Runnerable接口自理的run方法
class Demo implements Runnable { public void run() { for (int x = 0; x < 100; x++) System.out.println("demo " + x); } } class ThreadDemo2 { public static void main(String[] args) { Demo d = new Demo(); Thread t = new Thread(d); t.start(); for (int x = 0; x < 100; x++) System.out.println("main " + x); } }
多线程编程的时候,不同的线程,可能会访问同一资源,这样就可能导致一些问题:数据安全、死锁、等待等。
所以要对多线程共同操作的对象加锁:
class Ticket implements Runnable { private int ticket = 1000; Object obj = new Object(); public void run() { while (true) { synchronized (obj) { if (ticket > 0) { try { Thread.sleep(10); } catch (Exception e) { } System.out.println(Thread.currentThread().getName() + " sale: " + ticket--); } else break; } } } } public class ThreadDemo { public static void main(String[] args) { Ticket tick = new Ticket(); Thread t1 = new Thread(tick); t1.start(); Thread t2 = new Thread(tick); t2.start(); Thread t3 = new Thread(tick); t3.start(); Thread t4 = new Thread(tick); t4.start(); } }
值得注意的是:
synchronized (obj)里面的obj其实是一个锁。如果要让不同的线程的共享数据安全,那么对同一个数据操作的锁必须是同一把锁。
Synchronized 不光可以加在代码外,也可以加载方法上。加载在方法上,虽然没有写锁对象,但实际上锁对象是this。对于静态方法锁对象是本类。
一个死锁的代码:
class MyLock { static Object lockA = new Object(); static Object lockB = new Object(); } class DeadLock implements Runnable { private boolean flag; DeadLock(boolean flag) { this.flag = flag; }; public void run() { if (flag) { synchronized (MyLock.lockA) { System.out.println("ifout"); synchronized (MyLock.lockB) { System.out.println("ifin"); } } } else { synchronized (MyLock.lockB) { System.out.println("elseout"); synchronized (MyLock.lockA) { System.out.println("elsein"); } } } } } class DeadLockDemo { public static void main(String[] args) { Thread t1 = new Thread(new DeadLock(true)); Thread t2 = new Thread(new DeadLock(false)); t1.start(); t2.start(); } }
对于有多个消费者和多个生产者的情况,如果想要生产和消费交替发生。就需要LocK类和Condition类,下面是毕老师的一个双线程交替运行的代码,写得非常好,值得多看几遍:
import java.util.concurrent.locks.*; class ProducerConsumerDemo { public static void main(String[] args) { Resource r = new Resource(); Producer pro = new Producer(r); Consumer con = new Consumer(r); Thread t1 = new Thread(pro); Thread t2 = new Thread(pro); Thread t3 = new Thread(con); Thread t4 = new Thread(con); t1.start(); t2.start(); t3.start(); t4.start(); } } class Resource { private String name; private int count = 1; private boolean flag = false; private Lock lock = new ReentrantLock(); private Condition condition_pro = lock.newCondition(); private Condition condition_con = lock.newCondition(); public void set(String name) throws InterruptedException { lock.lock(); try { while (flag) condition_pro.await();// t1,t2 this.name = name + "--" + count++; System.out.println(Thread.currentThread().getName() + "...生产者.." + this.name); flag = true; condition_con.signal(); } finally { lock.unlock();// 释放锁的动作一定要执行。 } } // t3 t4 public void out() throws InterruptedException { lock.lock(); try { while (!flag) condition_con.await(); System.out.println(Thread.currentThread().getName() + "...消费者........." + this.name); flag = false; condition_pro.signal(); } finally { lock.unlock(); } } } class Producer implements Runnable { private Resource res; Producer(Resource res) { this.res = res; } public void run() { while (true) { try { res.set("+商品+"); } catch (InterruptedException e) { } } } } class Consumer implements Runnable { private Resource res; Consumer(Resource res) { this.res = res; } public void run() { while (true) { try { res.out(); } catch (InterruptedException e) { } } } }