黑马程序员-多线程
2013-09-23 20:26
239 查看
建立线程的方法:
一:继承Thread类。复写run方法。通过star()开启线程
二:定义类实现Runnable接口。复写run方法。通过Thread类建立线程对象。将Runnable接口的子类作为实际参数传递给Thread类的构造函数。调用Thread类的start方法开启线程并调用Runnable接口的run方法。
实现方式的好处:避免了单继承的局限性。
两种方法区别:
继承Thread:线程代码存放在Thread子类run方法中。
实现runnable:线程代码存在接口的子类的run方法中。
线程都有自己默认的名称。Thread—0开始。可以用this.getName()获取。
线程状态图:
![](https://img-blog.csdn.net/20130923202047781?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMjIyMjIzNw==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
安全问题:当多条语句同一个线程共享数据时,一个线程对多条语句只执行了一部分,还没执行完,另一个线程参与进来执行导致共享数据错误。因为在记录数值和赋值之间又有一个线程操作了共享数据,所以真实数值和赋值是不相等的。
解决办法:对多条操作共享数据的语句,只能让一个线程都执行完。在执行过程中其他线程不可以参与执行。
同步代码块:synchronnized(对象)
{
需要同步的代码;
}
对象如同锁,持有锁的线程可以在同步中执行。没有持有锁的线程无法获取cpu执行权。
同步的前提:
1.必须要有两个或者两个以上线程。
2.必须是多个线程使用同一个锁。
弊端:多个线程都需要判断锁。较消耗资源。
同步函数:可在函数返回值前加上synchronized修饰。锁为this。
静态同步函数:锁为字节码文件对象。类名.class。该类类型为class。
单例设计模式的两种方式:
死锁:嵌套同步中出现。
线程间通讯:其实就是多个线程在操作统一资源,但是操作动作不同。
等待唤醒机制
锁.wait();
锁.notify();唤醒第一个等待的线程。
锁.notifyAll();唤醒所有等待线程。
线程多用while判断。因为if只判断一次。notify唤醒本方线程造成数据错乱。
为什么操作线程的方法要定义在Object类中?
因为这些方法在操作同步中线程时,都必须标识他们所操作的线程持有的锁,只有同一个锁上的被等待的线程可以被同一个锁上的notify唤醒。不可以对不同锁中的线程进行唤醒。锁可以是任意对象。所以定义在Object中。
1.5开始Lock,Condition
java.util.concurrent.locks.*;
如果停止线程?
只有一种,run方法结束。开启多线程运行,运行代码通常是循环结构。只要控制住循环,就能让run方法结束。即线程结束。
特殊情况:当线程处于冻结状态,就不会读到标记。那么线程就不会结束。
interrupt:冻结状态被强制变成运行状态。
stop:终止线程。
守护线程:t.setDeamon(ture); 后台线程。主线程结束随即结束。
join方法:当A线程执行到了B线程的.join()方法时,A会等待。等待B线程都执行完,A才会执行。
join可以用来临时加入线程执行。
A.start();
A.jion();
B.start();
主线程读到A.jion()时将会释放执行权,使A获取执行权,A执行完毕后,B和主线程开始交替执行。
A.start();
B.start();
A.jion();
主线程读到A.jion()时将会释放执行权,A.B随即获取执行权,A执行完毕后。主线程才能获取执行权。
线程优先级
setPriority();
暂停线程(释放执行权):Thread.yield();
多线程的应用:当某些代码需要被同时执行时。就用代码同时封装。
可用匿名内部的方式对代码进行封装:
new Thread()
{
public void run ()
{
执行代码;
}
}.start();
Runnable r = new Runnable()
{
public void run()
{
}
};
r.start();
一:继承Thread类。复写run方法。通过star()开启线程
二:定义类实现Runnable接口。复写run方法。通过Thread类建立线程对象。将Runnable接口的子类作为实际参数传递给Thread类的构造函数。调用Thread类的start方法开启线程并调用Runnable接口的run方法。
class Ticket { public void run() { } } Ticket t = new Ticket(); Thread t1 = new Thread(t); t1.start();
实现方式的好处:避免了单继承的局限性。
两种方法区别:
继承Thread:线程代码存放在Thread子类run方法中。
实现runnable:线程代码存在接口的子类的run方法中。
线程都有自己默认的名称。Thread—0开始。可以用this.getName()获取。
线程状态图:
安全问题:当多条语句同一个线程共享数据时,一个线程对多条语句只执行了一部分,还没执行完,另一个线程参与进来执行导致共享数据错误。因为在记录数值和赋值之间又有一个线程操作了共享数据,所以真实数值和赋值是不相等的。
解决办法:对多条操作共享数据的语句,只能让一个线程都执行完。在执行过程中其他线程不可以参与执行。
同步代码块:synchronnized(对象)
{
需要同步的代码;
}
对象如同锁,持有锁的线程可以在同步中执行。没有持有锁的线程无法获取cpu执行权。
同步的前提:
1.必须要有两个或者两个以上线程。
2.必须是多个线程使用同一个锁。
弊端:多个线程都需要判断锁。较消耗资源。
同步函数:可在函数返回值前加上synchronized修饰。锁为this。
静态同步函数:锁为字节码文件对象。类名.class。该类类型为class。
class Res { private String name; private String sex; private boolean flag = false; public synchronized void set(String name,String sex) { if(flag) try{this.wait();}catch(Exception e){} this.name = name; this.sex = sex; flag = true; this.notify(); } public synchronized void out() { if(!flag) try{this.wait();}catch(Exception e){} System.out.println(name+"........"+sex); flag = false; this.notify(); } } class Input implements Runnable { private Res r ; Input(Res r) { this.r = r; } public void run() { int x = 0; while(true) { if(x==0) r.set("mike","man"); else r.set("丽丽","女女女女女"); x = (x+1)%2; } } } class Output implements Runnable { private Res r ; Output(Res r) { this.r = r; } public void run() { while(true) { r.out(); } } } class InputOutputDemo2 { public static void main(String[] args) { Res r = new Res(); new Thread(new Input(r)).start(); new Thread(new Output(r)).start(); /* Input in = new Input(r); Output out = new Output(r); Thread t1 = new Thread(in); Thread t2 = new Thread(out); t1.start(); t2.start(); */ } }
单例设计模式的两种方式:
//一,饿汉式: class Demo { private Demo(){} private static final Demo d= new Demo(); public static Demo getDemo() { return d; } } //二,懒汉式 class Demo { private Demo(){} private static Demo d = null; public static Demo getDemo() { if(d==null) { synchronized(Demo.class) { if(d==null) d= new Demo(); } } return d; } }
死锁:嵌套同步中出现。
class Input implements Runnable { private Res r ; Input(Res r) { this.r = r; } public void run() { int x = 0; while(true) { synchronized(r) { if(r.flag) try{r.wait();}catch(Exception e){} if(x==0) { r.name="mike"; r.sex="man"; } else { r.name="丽丽"; r.sex = "女女女女女"; } x = (x+1)%2; r.flag = true; r.notify(); } } } } class Output implements Runnable { private Res r ; Output(Res r) { this.r = r; } public void run() { while(true) { synchronized(r) { if(!r.flag) try{r.wait();}catch(Exception e){} System.out.println(r.name+"...."+r.sex); r.flag = false; r.notify(); } } } } class InputOutputDemo { public static void main(String[] args) { Res r = new Res(); Input in = new Input(r); Output out = new Output(r); Thread t1 = new Thread(in); Thread t2 = new Thread(out); t1.start(); t2.start(); } }
线程间通讯:其实就是多个线程在操作统一资源,但是操作动作不同。
等待唤醒机制
锁.wait();
锁.notify();唤醒第一个等待的线程。
锁.notifyAll();唤醒所有等待线程。
线程多用while判断。因为if只判断一次。notify唤醒本方线程造成数据错乱。
为什么操作线程的方法要定义在Object类中?
因为这些方法在操作同步中线程时,都必须标识他们所操作的线程持有的锁,只有同一个锁上的被等待的线程可以被同一个锁上的notify唤醒。不可以对不同锁中的线程进行唤醒。锁可以是任意对象。所以定义在Object中。
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(); } } /* 对于多个生产者和消费者。 为什么要定义while判断标记。 原因:让被唤醒的线程再一次判断标记。 为什么定义notifyAll, 因为需要唤醒对方线程。 因为只用notify,容易出现只唤醒本方线程的情况。导致程序中的所有线程都等待。 */ class Resource { private String name; private int count = 1; private boolean flag = false; // t1 t2 public synchronized void set(String name) { while(flag) try{this.wait();}catch(Exception e){}//t1(放弃资格) t2(获取资格)//放弃资格就代表释放锁,其他线程可以进入 this.name = name+"--"+count++; System.out.println(Thread.currentThread().getName()+"...生产者.."+this.name); flag 4000 = true; this.notifyAll(); } // t3 t4 public synchronized void out() { while(!flag) try{wait();}catch(Exception e){}//t3(放弃资格) t4(放弃资格) System.out.println(Thread.currentThread().getName()+"...消费者........."+this.name); flag = false; this.notifyAll(); } } class Producer implements Runnable { private Resource res; Producer(Resource res) { this.res = res; } public void run() { while(true) { res.set("+商品+"); } } } class Consumer implements Runnable { private Resource res; Consumer(Resource res) { this.res = res; } public void run() { while(true) { res.out(); } } }
1.5开始Lock,Condition
java.util.concurrent.locks.*;
import java.util.concurrent.locks.*; class ProducerConsumerDemo2 { 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(); } } /* JDK1.5 中提供了多线程升级解决方案。 将同步Synchronized替换成现实Lock操作。 将Object中的wait,notify notifyAll,替换了Condition对象。 该对象可以Lock锁 进行获取。 该示例中,实现了本方只唤醒对方操作。 Lock:替代了Synchronized lock unlock newCondition() Condition:替代了Object wait notify notifyAll await(); signal(); signalAll(); */ class Resource { private String name; private int count = 1; private boolean flag = false; // t1 t2 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) { } } } }
如果停止线程?
只有一种,run方法结束。开启多线程运行,运行代码通常是循环结构。只要控制住循环,就能让run方法结束。即线程结束。
特殊情况:当线程处于冻结状态,就不会读到标记。那么线程就不会结束。
class StopThread implements Runnable { private boolean flag =true; public void run() { while(flag) { System.out.println(Thread.currentThread().getName()+"....run"); } } public void changeFlag() { flag = false; } } class StopThreadDemo { public static void main(String[] args) { StopThread st = new StopThread(); Thread t1 = new Thread(st); Thread t2 = new Thread(st); t1.setDaemon(true); t2.setDaemon(true); t1.start(); t2.start(); int num = 0; while(true) { if(num++ == 60) { //st.changeFlag(); //t1.interrupt(); //t2.interrupt(); break; } System.out.println(Thread.currentThread().getName()+"......."+num); } System.out.println("over"); } }
interrupt:冻结状态被强制变成运行状态。
stop:终止线程。
守护线程:t.setDeamon(ture); 后台线程。主线程结束随即结束。
join方法:当A线程执行到了B线程的.join()方法时,A会等待。等待B线程都执行完,A才会执行。
join可以用来临时加入线程执行。
A.start();
A.jion();
B.start();
主线程读到A.jion()时将会释放执行权,使A获取执行权,A执行完毕后,B和主线程开始交替执行。
A.start();
B.start();
A.jion();
主线程读到A.jion()时将会释放执行权,A.B随即获取执行权,A执行完毕后。主线程才能获取执行权。
线程优先级
setPriority();
暂停线程(释放执行权):Thread.yield();
多线程的应用:当某些代码需要被同时执行时。就用代码同时封装。
可用匿名内部的方式对代码进行封装:
new Thread()
{
public void run ()
{
执行代码;
}
}.start();
Runnable r = new Runnable()
{
public void run()
{
}
};
r.start();
相关文章推荐
- 黑马程序员—ASP.net中多线程
- 黑马程序员--视频随笔记录--多线程1
- 黑马程序员_Java 多线程
- 黑马程序员---多线程视频之经验浅谈
- 黑马程序员--Java 多线程与并发总结
- 黑马程序员---Java基础--11天(多线程)
- 黑马程序员_java 多线程笔记
- 黑马程序员——多线程
- 黑马程序员—多线程的实现过程
- 黑马程序员——【Java基础】——多线程
- 黑马程序员-java学习之多线程
- 黑马程序员_多线程
- 黑马程序员——Java语言基础:多线程
- 黑马程序员——多线程之线程安全的实现详解
- 黑马程序员-学习日记(多线程安全问题和死锁认识)
- 黑马程序员——多线程
- 黑马程序员学习日记----多线程(二)
- [黑马程序员]--Java语言基础-多线程
- 黑马程序员-java学习笔记-多线程
- 黑马程序员-----多线程