1.线程的基本概念 线程是一个程序里面不同的执行路径 在同一个时间点,一个cpu只能有一个线程在执行。 2.线程的创建与启动 第一种更好,因为一个类只能集成一个父类,而可以实现很多接口 第一种 定义线程实现Runnable接口 package com.anker.thread; public class TestThread1 { public static void main(String args[]) { Runner1 r = new Runner1(); // r.run(); 直接调用等于方法调用,而非新启线程 Thread t = new Thread(r); t.start(); for (int i = 0; i < 100; i++) { System.out.println("Main Thread:" + i); } } } class Runner1 implements Runnable { @Override public void run() { for (int i = 0; i < 100; i++) { System.out.println("Runner1:" + i); } } } 第二种 集成Thread package com.anker.thread; public class TestThread2 { public static void main(String args[]) { Runner2 r = new Runner2(); r.start(); for (int i = 0; i < 100; i++) { System.out.println("Main Thread:" + i); } } } class Runner2 extends Thread { @Override public void run() { for (int i = 0; i < 100; i++) { System.out.println("Runner1:" + i); } } } 线程的状态: start->就绪状态->运行状态->->终止 运行状态中会存在以下状态: 阻塞状态:sychronized同步块,需要等待对象锁或类锁 waiting: 调用object.wait,将当前线程处于等待状态,并将对象锁释放,等待notify或者notifyAll()唤醒。 注意:使用notify,在众多等待同一个锁的任务中只有一个被唤醒,而使用notifyAll唤醒的是等待同一个锁的所有任务。 注意是等待同一个锁。 sleep:Thread.sleep(),将当前线程处于sleep状态,但仍持有线程资源。 interrupt: 外部通过interrupt方法,将从sleep状态中唤醒。 线程的方法: isAlive:线程是否终止 getPriority(): 获得线程的优先级 setPriority(): 设置线程的优先级(每个线程有自己的优先级,优先级越高的获得的cpu时间越多) Thread.sleep(): 将当前线程睡眠指定毫秒数,但仍然持有线程资源 Thread.interrupt(); //中断线程, 此方法适用于将线程从sleep状态中唤醒。 public boolean Thread.isInterrupted() //判断是否中断 public static boolean Thread.interrupted() //判断是否中断,并清除当前中断状态。 join(): 调用某线程的该方法,将当前线程与该线程"合并",即等待该线程结束,再 恢复当前线程的运行 join的本质是 while(isAlive()) { wait(0); } 待线程执行完毕后,系统会调用notifyAll()。因此不建议在Thread实例中使用wait和notify()方法。有可能影响到API的调用。 yield(): 让出cpu,当前线程进入就绪队列等待调度(只是下一次的执行机会让给其他线程) wait(): 当前线程进入对象的wait pool,与sleep不同,sleep在休眠过程的时候仍然持有锁,而wait会释放锁, 直到其他线程唤醒。 notify()/notifyAll():唤醒对象的wait pool中的一个/所有等待线程 挂起(suspend) 和继续执行(resume)线程,不建议使用此两个函数 --suspend 不会释放锁 --如果加锁在resume()之前,则发生死锁。 Thread.stop()不推荐使用,它会释所有monitor。 重新的方法不能抛出跟父类方法不同的异常 3.线程的调度和优先级 java提供一个线程调度器来监控程序中启动进入就绪状态的所有线程, 线程调度器按照线程的优先级决定调度那个进程来执行(优先级高的获得更多的cpu执行时间) 线程的优先级用数字来表示,范围从1到10,一个线程的缺省优先级是5 Thread.MIN_PRIORITY=1 Thread.MAX_PRIORITY=10 Thread.MNORM_PRIORITY=5 使用下述方法获得或设置对象的优先级 int getPriority(); void setPriority(int newPriority); --Interrupt中断线程示例 --Interrupt方法是中断线程的一种优雅方式 public class Test implements Runnable{ public static void main(String args[]) { Test r = new Test(); Thread t1 = new Thread(r); t1.start(); for(int j=0;j<100;j++){ System.out.println("j:"+j); } t1.interrupt(); } // public void run() { // while(true){ // if(Thread.currentThread().isInterrupted()){ //检测是否中断 // System.out.println("thead is interrupt"); // break; // } // try { // System.out.println("sleep"); // Thread.sleep(100000); // } catch (InterruptedException e) { // // TODO Auto-generated catch block // System.out.println("interrupted when Sleep"); //// Thread.currentThread().interrupt();//设置中断状态,抛出异常后会自动清除中断标记位 // } // } // // } public void run() { while (true) { if (Thread.currentThread().isInterrupted()) {//判断当前线程是否发生中断,若是则break; System.out.println("thead is interrupt"); break; } } } --Join示例 //结果:打印完i之后,再打印j //join方式是将线程合并到主线程,待线程之后完之后,才会继续执行主线程的逻辑。 public static void main(String args[]) { Test1 r = new Test1(); Thread t1 = new Thread(r); t1.start(); try { t1.join(); } catch (InterruptedException e) { e.printStackTrace(); } for(int j=0;j<100;j++){ System.out.println("j:"+j); } } public void run() { for(int i=0;i<100;i++){ System.out.println("i:"+i); } } 线程同步 所有同步的状态都要考虑加synchronized方法 在Java语言中,引入对象互斥锁的概念,保证共享数据操作的完整性,每个对象对应于 一个可称为"互斥锁"的标记,这个标记保证在任一时刻,只能有一个线程访问该对象。 当对象调用其任意synchronized方法的时候,此对象都被加锁, 这时该对象上的其他synchronized方法只有等到前一个方法调用完毕并释放了锁之后才被调用。 synchronized(xxx),指锁定xxx对象,只能有一个线程访问xxx对象,不相同的对象,是可以同步访问。 当关键字synchronized修饰方法时,是指锁定当前调用对象,等同于synchronized(this){} –1. 指定加锁对象:对给定对象加锁,进入同步代码前要获得给定对象的锁。 public void run() { for(int j=0;j<10000000;j++){ synchronized(instance){ i++; } } –2. 直接作用于实例方法:相当于对当前实例加锁,进入同步代码前要获得当前实例的锁。等同于方法1的synchronized(this){...代码块..} public synchronized void increase(){ i++; } –3. 直接作用于静态方法:相当于对当前类加锁,进入同步代码前要获得当前类的锁,即使不同的对象访问此段代码,也要依次访问。 public static synchronized void increase(){ i++; } package com.anker.thread; public class TT implements Runnable{ int b = 100; public synchronized void m1() throws Exception { System.out.println("执行m1方法"); b = 1000; Thread.sleep(5000); System.out.println("b= "+b); } public synchronized void m2() throws Exception{ System.out.println("执行m2方法"); Thread.sleep(2500); b=2000; System.out.println("b:"+b); } @Override public void run() { try { System.out.println("执行run方法"); m1(); } catch (Exception e) { e.printStackTrace(); } } public static void main(String args[]) throws Exception{ TT tt = new TT(); Thread t = new Thread(tt); t.start(); tt.m2(); System.out.println(tt.b); } } --在static方法上增加synchronized,即意味着持有类锁,不同的对象仍要依次访问。 //结果为20000000 public class AccountingSyncClass implements Runnable{ static int i=0; public static synchronized void increase(){ i++; } public void run() { for(int j=0;j<10000000;j++){ increase(); } } public static void main(String[] args) throws InterruptedException { Thread t1=new Thread(new AccountingSyncClass()); Thread t2=new Thread(new AccountingSyncClass()); t1.start();t2.start(); t1.join();t2.join(); System.out.println(i); } } // wait() 必须在synchronized 函数或者代码块里面 // wait()会让已经获得synchronized 函数或者代码块控制权的Thread暂时休息,并且丧失控制权 // 这个时候,由于该线程丧失控制权并且进入等待,其他线程就能取得控制权,并且在适当情况下调用notifyAll()来唤醒wait()的线程。 // 需要注意的是,被唤醒的线程由于已经丧失了控制权,所以需要等待唤醒它的线程结束操作,从而才能重新获得控制权。 // 所以wait()的确是马上让当前线程丧失控制权,其他的线程可以乘虚而入。 // 所以wait()的使用,必须存在2个以上线程,而且必须在不同的条件下唤醒wait()中的线程。 // 当存在多个等待线程时, notify是随机选择等待的线程进行唤醒。 //结果打印顺序 T1 start! T1 wait for object T2 start! notify one thread T2 end! T1 end! public class TestWait { final static Object object = new Object(); public static class T1 extends Thread{ public void run() { synchronized (object) { System.out.println(System.currentTimeMillis()+":T1 start! "); try { System.out.println(System.currentTimeMillis()+":T1 wait for object "); object.wait(); //如果当前线程不是锁的持有者,该方法抛出一个IllegalMonitorStateException异常。这里需要采用锁对象的的对象 } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(System.currentTimeMillis()+":T1 end!"); } } } public static class T2 extends Thread{ public void run() { synchronized (object) { System.out.println(System.currentTimeMillis()+":T2 start! notify one thread"); object.notify(); System.out.println(System.currentTimeMillis()+":T2 end!"); try { Thread.sleep(2000); } catch (InterruptedException e) { } } } } public static void main(String[] args) { Thread t1 = new T1() ; Thread t2 = new T2() ; // Thread t1_1 = new T1() ; // t1_1.start(); t1.start(); t2.start(); } } 消费者与生产者的故事 package com.anker.thread; public class ProducerConsumer { public static void main(String args[]){ SynStack ss = new SynStack(); Producer p = new Producer(ss); Consumer c = new Consumer(ss); new Thread(p).start(); new Thread(c).start(); } } class WoTou{ int id; WoTou(int id){ this.id = id; } public String toString(){ return "WoTou:"+id; } } class SynStack{ int index = 0; WoTou[] arrWT = new WoTou[6]; public synchronized void push(WoTou wt){ while(index == arrWT.length){//使用while会确保线程被打断时,仍然要执行判断 try { System.out.println("push wait方法被调用"); this.wait();//只能在同步控制方法或同步块中调用wait()、notify()和notifyAll()。如果在非同步的方法里调用这些方法抛出异常 } catch (InterruptedException e) { e.printStackTrace(); } } this.notify(); arrWT[index] = wt; System.out.println("push WoTou index:"+index); index ++; } public synchronized WoTou pop(){ while(index == 0){ try { System.out.println("pop wait方法被调用"); this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } this.notify(); index --; System.out.println("pop WoTou index:"+index); return arrWT[index]; } } class Producer implements Runnable{ SynStack ss = null; Producer(SynStack ss){ this.ss = ss; } @Override public void run() { for(int i=0;i<20;i++){ WoTou wt= new WoTou(i); ss.push(wt); // System.out.println("WtTou is produced:"+wt); try{ Thread.sleep((int)(Math.random() * 1000)); }catch (InterruptedException e) { e.printStackTrace(); } } } } class Consumer implements Runnable{ SynStack ss = null; Consumer(SynStack ss){ this.ss = ss; } @Override public void run() { for(int i=0;i<20;i++){ WoTou wt= ss.pop(); // System.out.println("WtTou is consumer:"+wt); try{ Thread.sleep((int)(Math.random() * 1000)); }catch (InterruptedException e) { e.printStackTrace(); } } } }
相关推荐
电子书相关:包含4个有关JAVA线程的电子书(几乎涵盖全部有关线程的书籍) OReilly.Java.Threads.3rd.Edition.Sep.2004.eBook-DDU Java Thread Programming (Sams) java线程第二版中英文 java线程第二版中英文 ...
Java线程讲解Java线程讲解Java线程讲解Java线程讲解Java线程讲解Java线程讲解Java线程讲解Java线程讲解Java线程讲解Java线程讲解
java 线程Dump 分析工具: Java的TDA线程转储分析器是一个用于分析Sun Java VM生成的线程转储和堆信息的小型Swing GUI(目前用1.4测试)。它从提供的日志文件中解析线程转储和类直方图。它提供关于发现的线程转储的...
Java线程Java线程Java线程Java线程Java线程Java线程Java线程Java线程Java线程Java线程Java线程Java线程Java线程Java线程Java线程
分析java线程日志的工具,使用jstack把java线程日志dump下来,然后上传到该工具,就可以查看线程阻塞情况等信息。
4种常用Java线程锁的特点,性能比较、使用场景 线程(thread)是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发...
Java线程模块Java线程之秒表新手学习Java线程模块时,利用Java中设置线程的暂停间隔,做的简易秒表
java线程.pdf java 学习java
java线程 线程 教程 java线程教程 java线程学习资料 本教程有什么内容? 本教程研究了线程的基础知识— 线程是什么、线程为什么有用以及怎么开始编写使用线程的简单 程序。 我们还将研究更复杂的、使用线程的应用...
Java线程状态流转图
Java线程Java线程Java线程Java线程Java线程Java线程
有点乐趣,小java线程监控程序, 小java线程监控程序 小java线程监控程序
Java线程.pdf
Java线程使用教程
Java线程pdf帮助文档
java线程深入讲解,可以了解java线程同步语安全,实现的方法和synchronized锁的使用与安全控制等等,谁用谁知道好用
Java 线程通信示例 源代码 多线程之间通信,值得收藏
Java 线程的学习和使用Java 线程的学习和使用
这是一个关于Java线程的ppt文件,燕山大学信息学院计算机系 李 峰
java 线程java 线程java 线程java 线程java 线程java 线程java 线程java 线程java 线程