黑马程序员-----线程
来源:互联网 发布:淘宝客越来越难做 编辑:程序博客网 时间:2024/06/03 16:26
------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------线程
一、概述
进程:指正在运行的程序,负责这个程序的内存空间分配,代表该程序在内存中的执行区域。
线程:就是在一个进程中负责一个执行路径。
多线程:就是在一个进程中多个执行路径同时执行。
多线程的好处:
1. 一个进程里面可以同时运行多个任务。
2. 提供资源的利用率。
多线程的弊端:
1. 降低了一个进程里面的线程的执行频率。
2. 对线程进行管理要求额外的 CPU开销,会给系统带来上下文切换的额外负担。
3. 当多个线程需要对公有变量进行写操作时,可能发生线程安全问题。
4. 线程的死锁。
线程的状态:
创建:新创建了一个线程对象。
可运行:线程对象创建后,其他线程调用了该对象的start()方法。该状态的线程位于可运行线程池中,变得可运行,等待获取cpu的执行权。
运行:就绪状态的线程获取了CPU执行权,执行程序代码。
阻塞: 阻塞状态是线程因为某种原因放弃CPU使用权,暂时停止运行。直到线程进入就绪状态,才有机会转到运行状态。
死亡:线程执行完它的任务时。
二、创建线程的方式
1、继承Thread类
步骤:
1. 定义一个类继承Thread类。
2. 覆盖Thread类中的run方法。
3. 直接创建Thread的子类对象创建线程。
4. 调用start方法开启线程并调用线程的任务run方法执行。
练习:
class Demo extends Thread{ private String name ; Demo(String name){ this.name = name; } public void run(){ for(int x = 0; x < 10; x++){ System.out.println(name + "...x=" + x + "...ThreadName=" + Thread.currentThread ().getName()); } }}class ThreadDemo{ public static void main(String[] args){ Demo d1 = new Demo("线程1"); Demo d2 = new Demo("线程2"); //开启线程,调用run方法。 d1.start(); d2.start(); for(int x = 0; x < 20; x++){ System.out.println("x = " + x + "...over..." + Thread.currentThread().getName()); } }}
2、实现Runnable接口
避免了Java单继承的局限性,创建线程的第二种方式较为常用。
步骤:
1:定义了实现Runnable接口
2:重写Runnable接口中的run方法,就是将线程运行的代码放入在run方法中
3:通过Thread类建立线程对象
4:将Runnable接口的子类对象作为实际参数,传递给Thread类构造方法
5:调用Thread类的start方法开启线程,并调用Runable接口子类run方法
//需求:简单的卖票程序。多个窗口卖票。class Ticket implements Runnable{private int tick = 100;public void run(){while(true){if(tick>0){//显示线程名及余票数System.out.println(Thread.currentThread().getName()+":sale -- "+ tick--);}}}}class TicketDemo{public static void main(String[] args) {//创建卖票线程实例对象Ticket t = new Ticket();//四个线程代表四个窗口在卖票Thread t1 = new Thread(t);Thread t2 = new Thread(t);Thread t3 = new Thread(t);Thread t4 = new Thread(t); //启动线程 t1.start(); t2.start(); t3.start(); t4.start(); }}三、线程安全
2. 操作共享数据的线程代码有多条。
解决办法:
对多条操作共享数据的语句,只能让一个线程都执行完。在执行过程中,其他线程不可以参与执行。一种是同步代码块,还有就是同步函数。都是利用关键字synchronized来实现。
1、同步代码块
class Ticket implements Runnable{ private int num = 100; Object obj = new Object(); public void run(){ while(true ){ synchronized(obj ){//要同步的代码块 if(num > 0){ System.out.println(Thread.currentThread().getName() + "...sale..." + num--); } } } }}class TicketDemo{ public static void main(String[] args){ Ticket t = new Ticket(); Thread t1 = new Thread(t); Thread t2 = new Thread(t); Thread t3 = new Thread(t); Thread t4 = new Thread(t); t1.start(); t2.start(); t3.start(); t4.start(); }}
2、同步函数
class Bank{ private int sum ; public synchronized void add(int num){ //同步函数 sum = sum + num; System.out.println("sum = " + sum); }}
同步函数和同步代码块的区别:
2. 同步代码块的锁是任意的对象。
建议使用同步代码块。
//加同步的单例设计模式————懒汉式class Single{private static Single s = null;private Single(){}public static void getInstance(){if(s==null){synchronized(Single.class){if(s==null)s = new Single();}}return s;}}死锁出现情况:
1:两个任务以相反的顺序申请两个锁,死锁就可能出现
2:线程T1获得锁L1,线程T2获得锁L2,然后T1申请获得锁L2,同时T2申请获得锁L1,此时两个线程将要永久阻塞,死锁出现
四、线程通讯
多个线程操作同一资源,但操作动作不一样需要线程通讯
1、使用同步操作同一资源
//多消费者和生产者//资源class Resource{ private String name ; private int count = 1; private boolean flag = false; public synchronized void set(String name){ while(flag ) try{ //让线程处于冻结状态,被wait的线程会被存储到线程池中。 this.wait(); } catch(InterruptedException e){ e.printStackTrace(); } this.name = name + count; count++; System.out.println(Thread.currentThread().getName() + "...生产者..." + this. name); flag = true ; //唤醒线程池中所有线程 notifyAll(); } public synchronized void out(){ while(!flag ) try{ this.wait(); } catch(InterruptedException e){ e.printStackTrace(); } flag = false ; notifyAll(); System.out.println(Thread.currentThread().getName() + "...消费者..." + this. name); }}//生产者线程class Producer implements Runnable{ private Resource r ; Producer(Resource r){ this.r = r; } public void run(){ while(true ){ r.set( "烤鸭"); } }}//消费者线程class Consumer implements Runnable{ private Resource r ; Consumer(Resource r){ this.r = r; } public void run(){ while(true ){ r.out(); } }}class ProducerConsumerDemo { public static void main(String[] args){ Resource r = new Resource(); Producer pro = new Producer(r); Consumer con = new Consumer(r); Thread t0 = new Thread(pro); Thread t1 = new Thread(pro); Thread t2 = new Thread(con); Thread t3 = new Thread(con); t0.start(); t1.start(); t2.start(); t3.start(); }}
2、JDK1.5新特性
lock():获取锁。
unlock():释放锁,为了防止异常出现,导致锁无法被关闭,所以锁的关闭动作要放在finally中。
Condition接口:出现替代了Object中的wait、notify、notifyAll方法。将这些监视器方法单独进行了封装,变成Condition监视器对象,可以任意锁进行组合。
Condition接口中的await方法对应于Object中的wait方法。
Condition接口中的signal方法对应于Object中的notify方法。
Condition接口中的signalAll方法对应于Object中的notifyAll方法。
import java.util.concurrent.locks.*;class Resource{ private String name ; private int count = 1; private boolean flag = false; //创建一个锁对象 Lock lock = new ReentrantLock(); //通过已有的锁获取该锁上的监视器对象 Condition con = lock .newCondition(); //通过已有的锁获取两组监视器,一组监视生产者,一组监视消费者 Condition producer_con = lock .newCondition(); Condition consumer_con = lock .newCondition(); public void set(String name){ lock.lock(); try{ while(flag ) try{ producer_con.await(); } catch(InterruptedException e){ e.printStackTrace(); } this.name = name + count; count++; System.out.println(Thread.currentThread().getName() + "...生产者..." + this. name); flag = true ; consumer_con.signal(); } finally{ lock.unlock(); } } public void out(){ lock.lock(); try{ while(!flag ) try{ consumer_con.await(); } catch(InterruptedException e){ e.printStackTrace(); } flag = false ; producer_con.signal(); System.out.println(Thread.currentThread().getName() + "...消费者..." + this. name); } finally{ lock.unlock(); } }}class Producer implements Runnable{ private Resource r ; Producer(Resource r){ this.r = r; } public void run(){ while(true ){ r.set( "烤鸭"); } } }class Consumer implements Runnable{ private Resource r ; Consumer(Resource r){ this.r = r; } public void run(){ while(true ){ r.out(); } }}class ProducerConsumerDemo { public static void main(String[] args){ Resource r = new Resource(); Producer pro = new Producer(r); Consumer con = new Consumer(r); Thread t0 = new Thread(pro); Thread t1 = new Thread(pro); Thread t2 = new Thread(con); Thread t3 = new Thread(con); t0.start(); t1.start(); t2.start(); t3.start(); }}
五、停止线程
public void run(){while(flag){System.out.println(Thread.currentThread().getName()+"....run");}}
2、当线程处于冻结状态。就不会读取到标记。那么线程就不会结束。需要对冻结进行清除。强制让线程恢复到运行状态中来。这样就可以操作标记让线程结束。Thread类提供该方法interrupt();
六、其他小方法1、join方法
当A线程执行到了b线程的.join()方法时,A线程就会等待,等B线程都执行完,A线程才会执行。(此时B和其他线程交替运行。)join可以用来临时加入线程执行。
2、setPriority()方法用来设置优先级
MAX_PRIORITY 最高优先级10
MIN_PRIORITY 最低优先级1
NORM_PRIORITY 分配给线程的默认优先级
3、yield()方法可以暂停当前线程,让其他线程执行。
- 黑马程序员之多线程
- 黑马程序员-----线程复习
- “黑马程序员”~线程例题
- 黑马程序员_线程
- 黑马程序员 线程总结
- 黑马程序员:线程池
- 黑马程序员-线程同步
- 黑马程序员-线程入门
- 黑马程序员----线程
- 黑马程序员-线程
- 黑马程序员-----线程
- 黑马程序员:java线程
- 黑马程序员--线程池
- 黑马程序员--C#线程
- 黑马程序员_线程
- 黑马程序员_线程
- 黑马程序员-----线程
- 黑马程序员---深入线程
- 【数据结构】二叉树的基本操作
- 关于__FILE__,dirname()的使用小小心得
- 简单了解JAVA8的新特性
- HDU 1027 Ignatius and the Princess II(求由1-n组成按字典序排序的第m个序列)
- 25.Oracle数据库SQL开发之 SQLPlus使用——保存、检索并运行文件
- 黑马程序员-----线程
- 物联网操作系统HelloX已成功移植到MinnowBoard MAX开发板上
- netty rpc 框架
- Android分享到微信好友、朋友圈
- 【数据结构】二维数组
- rsync同步工具
- Android工程出现错误Unable to resolve target 'android-19'
- 26.Oracle数据库SQL开发之 SQLPlus使用——格式化列
- Android相关文章的规划