黑马程序员_java基础--多线程
来源:互联网 发布:淘宝店面设计 知乎 编辑:程序博客网 时间:2024/06/07 04:20
多线程
1、线程类和实现多线程
进程:是一个正在执行中的程序。每一个进程执行都有一个执行顺序。该顺序是一个执行路径,或者叫一个控制单元。
线程:程序中的控制单元,线程在控制着进程的执行。
一个进程至少有一个线程。
Java VM 启动的时候会有一个进程java.exe。存在主线程,这个线程运行的代码存在于main方法中。
1.1、继承Thread类
定义类继承Thread.
复写Thread类中的run方法。
创建实例调用线程的start方法,该方法作用:启动线程,调用run方法。
如:
public class TreadDemo { //主线程 public static void main(String[] args) { // TODO Auto-generated method stub Thr1 t1 = new Thr1(); Thr2 t2 = new Thr2();//创建线程实例 t1.start();//调用start方法开启线程 t2.start(); int count = 1; for(int x=1;x<70;x++) System.out.println(Thread.currentThread().getName()+"..main...."+count++); }}//线程1class Thr1 extends Thread{ int count = 1; public void run(){ for(int x=1;x<60;x++) System.out.println(this.getName()+"...run1..."+count++); }}//线程2class Thr2 extends Thread{ int count = 1; public void run(){ for(int y=1;y<60;y++) System.out.println(this.getName()+"..run2....."+count++); }}
运行结果每次都不同
随机性
为什么要覆盖run方法呢?
Thread类用于描述线程。该类就定义了一个功能,用于存储线程要运行的代码。该存储功能就是run方法。
run和start方法.
状态图:
图 1-1
线程标识:名称:getName();线程拥有默认的名称:Thread-编号
void setName(String name) 改变线程名称,使之与参数 name 相同。
void setPriority(int newPriority) 更改线程的优先级。
Thread.currentThread()==this;获取当前线程。
sleep方法需要制定睡眠时间,单位是毫秒。一个特殊的状态:就绪。具备了执行资格,但是还没有获取资源。
static void yield() 暂停当前正在执行的线程对象,并执行其他线程。
void join() 调用该方法的线程需要执行完毕其他线程才会执行。
void interrupt() 束线程的冻结状态,使线程回到运行状态中来
1.2、实现Runnable接口。
class PrimeRun implements Runnable { long minPrime; PrimeRun(long minPrime) { this.minPrime = minPrime; } public void run() { // compute primes larger than minPrime //. . . } }
然后,下列代码会创建并启动一个线程:
PrimeRun p = new PrimeRun(143);
new Thread(p).start();
1.3 两种方法的区别
继承Thread:线程代码存放在Thread子类run方法中。
实现Runnable:线程代码存在接口的子类的run方法。
实现Runnable接口比继承Thread类所具有的优势:
1):适合多个相同的程序代码的线程去处理同一个资源
2):可以避免java中的单继承的限制
3):增加程序的健壮性,代码可以被多个线程共享,代码和数据独立。
售票例子:
多窗口售票
无效线程异常
public class TicketDemo { /** * @param args */ public static void main(String[] args) { Ticket tick = new Ticket(); Thread t1 = new Thread(tick); Thread t2 = new Thread(tick); Thread t3 = new Thread(tick); Thread t4 = new Thread(tick); t1.start(); t2.start(); t3.start(); t4.start(); }}class Ticket implements Runnable{ private int tickNum = 10; Object obj = new Object(); @Override public void run() { while(true){ synchronized(obj){ if(tickNum>0){ try{Thread.sleep(20);}catch(Exception e){} System.out.println(Thread.currentThread().getName()+"..run.."+tickNum--); } } } }}
2、多线程安全问题---同步
问题的原因:
当多条语句在操作同一个线程共享数据时,一个线程对多条语句只执行了一部分,还没有执行完,
另一个线程参与进来执行。导致共享数据的错误。
解决办法:
对多条操作共享数据的语句,只能让一个线程都执行完。在执行过程中,其他线程不可以参与执行。
同步代码块
synchronized(对象)
{
需要同步的代码
}
对象如同锁。持有锁的线程可以在同步中执行。没有持有锁的线程即使获取cpu的执行权,也进不去,因为没有获取锁。
共享数据
同步的前提:
1,必须要有两个或者两个以上的线程。
2,必须是多个线程使用同一个锁。
必须保证同步中只能有一个线程在运行。
好处:解决了多线程的安全问题。
弊端:多个线程需要判断锁,较为消耗资源,
同步函数
锁:this
同步静态函数
锁:类名.class
同步函数的锁是固定的this。
同步代码块的锁是任意的对象。
建议使用同步代码块。
单例设计模式
懒汉式
实例的延迟加载
class Single{ private Single(){} private static Single s = null; public static Single getInstance(){ if(s==null){ synchronized(Single.class){ if(s==null) s=new Single(); } } return s; }}
典型死锁:
public class DeadLockDemo { /** * @param args */ public static void main(String[] args) { Thread t1 = new Thread(new Test(true)); Thread t2 = new Thread(new Test(false)); t1.start(); t2.start(); }}class MyLock{ //定义两把锁 static Object locka = new Object(); static Object lockb = new Object();}class Test implements Runnable{ private boolean flag; Test(boolean flag){ this.flag = flag; } public void run(){ if(flag){ while(true){ synchronized(MyLock.locka){ System.out.println("if locka"); synchronized(MyLock.lockb){ //.... System.out.println("if lockb"); } } } }else{ while(true){ synchronized(MyLock.lockb){ System.out.println("else lockb"); synchronized(MyLock.locka){ //... System.out.println("else locka"); } } } } }}
3、线通信程间
存在安全问题,怎么解决这个问题呢?
等待唤醒机制
wait();
notify();
notifyAll();
为什么定义notifyAll,
因为需要唤醒对方线程。
因为只用notify,容易出现只唤醒本方线程的情况。导致程序中的所有线程都等待。
生产消费者
多个生产消费
while
notifyAll
public class ProCsuDemo { /** * @param args */ public static void main(String[] args) { Resource res = new Resource(); Producer pro = new Producer(res); Consumer con = new Consumer(res); Thread t1 = new Thread(pro); Thread t2 = new Thread(con); Thread t3 = new Thread(pro); Thread t4 = new Thread(con); t1.start(); t2.start(); t3.start(); t4.start(); }}class Resource{ private int count = 1; private String name; private boolean flag = false; public synchronized void set(String name){ while(flag){ try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } this.name = name +"--"+ (count++); System.out.println(Thread.currentThread().getName()+".....生产者..."+this.name); flag = true; this.notifyAll(); } public synchronized void out(){ while(!flag){ try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println(Thread.currentThread().getName()+"...消费者..."+this.name); flag = false; this.notifyAll(); }}class Producer implements Runnable{ private Resource res; Producter(Resource res){ this.res = res; } @Override 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(); } }}
4、JDK1.5的新特性
java.util.concurrent.locks
Lock类
上锁
lock();
解锁
unlock();
Condition类
await();
signal();
signalAll();
class X { private final Lock lock = new ReentrantLock(); // ... public void m() { lock.lock(); // block until condition holds try { // ... method body } finally { lock.unlock() } } }
生成消费者
import java.util.concurrent.locks.Condition;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;public class ProCsuDemo2 { /** * @param args */ public static void main(String[] args) { Resource2 res = new Resource2(); Producter2 pro = new Producter2(res); Consumer2 con = new Consumer2(res); Thread t1 = new Thread(pro); Thread t2 = new Thread(con); Thread t3 = new Thread(pro); Thread t4 = new Thread(con); t1.start(); t2.start(); t3.start(); t4.start(); }}class Resource2{ private int count = 1; private String name; final Lock lock = new ReentrantLock(); final Condition con_pro = lock.newCondition(); final Condition con_csu = lock.newCondition(); private boolean flag = false; public void set(String name){ lock.lock(); try { while(flag){ con_pro.await(); } this.name = name +"--"+ (count++); System.out.println(Thread.currentThread().getName()+".....生产者..."+this.name); flag = true; con_csu.signal(); } catch (Exception e) { e.printStackTrace(); }finally{ lock.unlock(); } } public void out(){ lock.lock(); try { while(!flag){ con_csu.await(); } System.out.println(Thread.currentThread().getName()+"...消费者..."+this.name); flag = false; con_pro.signal(); } catch (Exception e) { e.printStackTrace(); }finally{ lock.unlock(); } }}class Producter2 implements Runnable{ private Resource2 res; Producter2(Resource2 res){ this.res = res; } @Override public void run() { while(true){ res.set("+商品+"); } } }class Consumer2 implements Runnable{ private Resource2 res; Consumer2(Resource2 res){ this.res = res; } public void run(){ while(true){ res.out(); } }}
停止线程。
stop方法过时了
控制run方法控制线程结束。
Thread类
interrupt();冻结状态的线程强制清除。
守护线程:
setDaemon(true);
----------------
join();
申请加入执行,要执行权,结束之后其他线程才能执行。
优先级有1-10个等级
setPriority();
默认优先级为5;
MAX_PRIORITY
MIN_PRIORITY
NORM_PRIROITY
yield()方法;
稍微减少线程执行频率,暂停正在执行的线程,并执行其他线程。
使用匿名内部类书写线程
Thread t = new Thread(new Runnable(){
public void run(){}
});
t.start();
停止线程:
1,stop方法。
2,run方法结束。
怎么控制线程的任务结束呢?
任务中都会有循环结构,只要控制住循环就可以结束任务。
控制循环通常就用定义标记来完成。
但是如果线程处于了冻结状态,无法读取标记。如何结束呢?
可以使用interrupt()方法将线程从冻结状态强制恢复到运行状态中来,让线程具备cpu的执行资格。
当时强制动作会发生了InterruptedException,记得要处理
5、线程池(重要)jdk1.5新特性
java.util.concurrent包提供了线程池的实现
图 5-1
图 5-2
------- android培训、java培训、java学习型技术博客、期待与您交流! ----------- 黑马程序员_java基础--多线程
- 黑马程序员_java基础-多线程
- 黑马程序员_java基础--多线程
- 黑马程序员_java基础多线程
- 黑马程序员_java编程基础11多线程
- 黑马程序员_Java基础_多线程1
- 黑马程序员_Java基础_多线程2
- 黑马程序员_Java基础(4)--多线程
- 黑马程序员_java编程基础13 多线程
- 黑马程序员_java基础复习五多线程
- 黑马程序员_Java基础_多线程_11
- 黑马程序员_Java基础_多线程_12
- 黑马程序员_Java基础03_多线程
- 黑马程序员_java基础——多线程
- 黑马程序员_Java基础(4)--多线程
- 黑马程序员_Java基础(4)--多线程
- 黑马程序员_Java基础_多线程1
- 黑马程序员_Java基础_多线程2
- 串的处理
- cocos2d-x的初步学习十九之坦克大战六
- ECSHOP手机访问和电脑访问效果一样
- POJ2892 Tunnel Warfare
- 反素数
- 黑马程序员_java基础--多线程
- android UI布局
- 寻找数组中最大的K个数
- 13年7月7日 ACM 第一天培训
- 黑马程序员--String
- cmd运行java
- 全键盘输入法
- 新生赛暑假第一场 解题报告
- [034] 微信公众帐号开发教程第10篇-解析接口中的消息创建时间CreateTime