Java 线程

boys

贡献于2013-12-16

字数:8527 关键词: Java开发 Java

进程 每个独立运行的程序称为进程 线程 线程是一个程序内部可以并发执行的一条执行路径 一个进程可以包含一个或多个线程 线程实现(两种方式) 1….继承java.lang.Thread类 2….实现java.lang.Runnable接口 (推荐使用) 覆写Thread类或Runnable接口的run()方法来完成实际的工作, 通过调用Thread类的start()方法,启动线程 1.。实现Runnable接口实现线程 (这种方式灵活 推荐使用) public class ThreadDemo_1 { public static void main(String[] args) throws InterruptedException { //创建一个新线程 RunnableA runA=new RunnableA(); Thread threadA=new Thread(runA); threadA.start(); //启动线程 进入就绪状态 System.out.println("主线程:"+Thread.currentThread().getName()+"启动..."); for (int i = 1000; i < 2000; i++) { System.out.println("main-->"+i); } } } //实现java.lang.Runnable接口 定义线程 class RunnableA implements Runnable{ public void run() { System.out.println("线程:"+Thread.currentThread().getName()+"启动"); for (int i = 0; i < 1000; i++) { System.out.println("RunnableA***>"+i); } } } 2.继承Thread类实现线程 public class ThreadDemo_2 { public static void main(String[] args) { ThreadA threadA=new ThreadA("线程一"); ThreadB threadB=new ThreadB("线程二"); threadA.start();//启动线程 threadB.start(); } } //继承Thread类实现线程 class ThreadA extends Thread{ public ThreadA(String name){ super(name); } public void run() { //重写run方法 System.out.println(Thread.currentThread().getName()+"start.."); show(); } public void show(){ for (int i = 0; i < 100; i++) { System.out.println(Thread.currentThread().getName()+"====="+i); try { Thread.sleep(100); //线程休眠100毫秒 } catch (InterruptedException e) { e.printStackTrace(); return; } } } } class ThreadB extends Thread{ public ThreadB(String name){ super(name); } public void run(){ System.out.println(Thread.currentThread().getName()+"start.."); show(); } public void show(){ for (int i = 0; i < 100; i++) { System.out.println(Thread.currentThread().getName()+"-----"+i); try { Thread.sleep(100); //线程休眠100毫秒 } catch (InterruptedException e) { e.printStackTrace(); return; } } } } 线程的生命周期 新线程状态 产生一个Thread对象时生成一个新线程 这是仅仅是个空线程对象 还没有分配系统资源 可运行状态 当调用start()方法启动线程,并自动调用run() 方法 这时处于可运行状态 运行状态 指线程正占有CPU 并正在执行 挂起状态 当发生一下任何一种情况时,线程进入挂起状态 1.调用sleep方法进入睡眠状态; 2. 线程处于I/O等待; 3. 线程试图得到一个锁,该锁正被其他线程持有; 4. 线程使用wait()方法等待某个触发条件 终止状态 当run()方法运行结束,或别的线程调用stop()方法时,线程进入死亡状态 就绪状态 创建 运行状态 阻塞状态 终止状态 start() 线程的常用方法 start() 启动一个线程 run() 定义该线程的操作 sleep(long) 使线程睡眠一段时间,单位为毫秒 不释放锁标志 join() 合并线程 线程休眠 Thread.sleep(毫秒数) 它使当前线程进入等待状态,直到过了指定的时间后,但是过了指定时间后,线程又将变成可运行的,并且会回到调度程序的可运行线程队列中 当调用sleep()线程不会释放它的“锁标志” Thread.yield()方法并不引起休眠,它只是暂停当前线程 也有可能马上被执行 线程的终止 public class ThreadDemo_3 { public static void main(String[] args) { Runner runner=new Runner(); Thread thread=new Thread(runner); thread.start(); try { Thread.sleep(10000); //当前线程中断10秒 } catch (InterruptedException e) { e.printStackTrace(); } //thread.interrupt(); //通过抛出异常的形式中断线程 不推荐使用 另外不要使用stop() runner.setFlag(false); //安全终止线程的方式 } } class Runner implements Runnable{ private boolean flag=true; @Override public void run(){ while(flag){ System.out.println("当前系统时间:======"+new Date()); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); System.out.println("线程异常中断"); return; } } } public void setFlag(boolean flag) { this.flag = flag; } } 合并线程: public class ThreadDemo_4 { public static void main(String[] args) { Thread thread=new Thread(new ThreadOne()); thread.start(); int index=0; while(true){ if(index++ ==50){ try { thread.join(); //合并到当前线程 成为当前线程的一部分 } catch (InterruptedException e) { } } System.out.println("main===="+index); //index==50后 主线程的这段代码将得不到执行机会 try { Thread.sleep(100); } catch (InterruptedException e) {} } } } class ThreadOne implements Runnable { public void run() { while(true){ System.out.println("ThreadOne ==="+Thread.currentThread().getName()); try { Thread.sleep(100); } catch (InterruptedException e) {} } } } 后台线程 threadObj.setDaemon(true) 创建后台线程的线程结束时,后台线程也随之消亡 public class ThreadDemo_5 extends Thread { public void run() { while (true) { System.out.println(getName()); } } public static void main(String[] args) { ThreadDemo_5 dt = new ThreadDemo_5(); dt.setDaemon(true);//将指定的线程设置成后台线程 //创建后台线程的线程结束时,后台线程也随之消亡 dt.setName("后台线程"); dt.start(); for (int i = 0; i < 10; i++) { System.out.println(Thread.currentThread().getName() + " " + i); } } } 线程的优先级 指在多线程环境 优先级越高的线程得到的CPU时间片越多 优先级 由1-10表示 Thread.MIN_PRIORITY=1 Thread.MAX_PRIORITY=10 Thread.NORM_PRIORITY=5 默认 public class ThreadDemo_6 { public static void main(String[] args) { ThreadPriority thA1 = new ThreadPriority("线程一"); ThreadPriority thA2 = new ThreadPriority("线程二"); thA1.setPriority(Thread.MIN_PRIORITY); thA2.setPriority(Thread.MAX_PRIORITY); thA2.start(); thA1.start(); } } class ThreadPriority extends Thread { private long count = 0; public ThreadPriority(String name) { super(name); } public void run() { System.out.printf("%s开始执行%n", this.getName()); long start = System.currentTimeMillis(); // 记住线程启动时间 while (System.currentTimeMillis() - start < 1000) {// 执行十秒 count++; } System.out.printf("%s执行了%d次%n", this.getName(), count); } } 线程同步 一个程序中有多个线程在执行时,由于线程的执行循序无法预知, 为保证读写共享数据时的正确性,JAVA提供了一种同步机制, 用synchronized关键字来实现的 synchronized关键字的作用: 确保在某个时刻只有一个线程允许执行特定的代码块 线程同步原理 所有对象都有和自己关联的隐含监控器, 锁 如果要进入一个对象的监控器,只需调用有synchronized关键词修饰的方法。 当一个线程进入一个同步的方法时,所有其他试图调用同一实例中的该方法的线程必须等待。 synchronized两种使用方法 同步方法 同步对象(同步块) 同步方法例子: 同步方法只是对目标对象中同步方法进行同步 public class SynchronizedMethodDemo_1 { public static void main(String[] args) { Tickets tt = new Tickets(); new Thread(tt).start(); new Thread(tt).start(); new Thread(tt).start(); } } class Tickets implements Runnable { private int num = 100; public void run() { while (true) { if(num<=0){ break; } salingTickets(); } } //同步方法 public synchronized void salingTickets() { if (num > 0) { try { Thread.sleep(10); } catch (InterruptedException e) {} System.out.println(Thread.currentThread().getName() + " 正在卖票..."+ num--); } } } 同步对象例子: 同步对象把目标对象的所有方法全部都进行同步 public class SynchronizedObjectDemo_1 { public static void main(String[] args) { TicketB tt = new TicketB(); new Thread(tt).start(); new Thread(tt).start(); new Thread(tt).start(); } } class TicketB implements Runnable { private int num = 100; public void run() { while (true) { if (num <= 0) { break; } synchronized (this) { //锁定当前对象 salingTickets(); } } } public void salingTickets() { if (num > 0) { try { Thread.sleep(10); } catch (InterruptedException e) { } System.out.println(Thread.currentThread().getName() + " 正在卖票..."+ num--); } } } 线程死锁 线程死锁产生的直接原因是占用共享资源的线程正在请求其他共享资源, 而该资源正在被其他线程占用,且占用该资源的线程还在请求其他共享资源, 从而形成了线程永远无法得到继续执行所需要的资源, 进而导致线程无法继续运行,形成互相等待的局面 线程死锁的根源在于不适当的运用synchronized 线程死锁例子: public class DeadLockDemo { public static void main(String[] args) { final Object r1="我是对象1"; final Object r2="我是对象2"; ThreadR r=new ThreadR(); ThreadK k=new ThreadK(); r.setResource(r1, r2); k.setResource(r1, r2); r.start(); k.start(); } } class ThreadR extends Thread{ Object r1; Object r2; public void setResource(Object r1,Object r2){ this.r1=r1; this.r2=r2; } public void run(){ //锁定r1 synchronized (r1) { System.out.println("ThreadR:已经锁定r1 "+r1); System.out.println("ThreadR:试图锁定r2....."); synchronized(r2){ //由于ThreadR正在试图锁定可能已经被ThreadK锁定的资源, //程序已经阻塞,下面的代码得不到执行 System.out.println("ThreadR:锁定r2"+r2); } } } } class ThreadK extends Thread{ Object r1; Object r2; public void setResource(Object r1,Object r2){ this.r1=r1; this.r2=r2; } public void run(){ //锁定r2 synchronized (r2) { System.out.println("ThreadK:已经锁定r2 "+r2); System.out.println("ThreadK:试图锁定r1....."); synchronized(r1){ //由于ThreadR正在试图锁定可能已经被ThreadK锁定的资源, //程序已经阻塞 System.out.println("ThreadK:锁定r1"); } } } } 多线程之间通讯 Object的wait和notify机制 生产者和消费者问题 假设仓库中只能存放一件产品,生产者将生产出来的产品放入仓库,消费者将仓库中产品取走消费 如果仓库中没有产品,则生产者将产品放入仓库,否则停止生产并等待,直到仓库中的产品被消费者取走为止 如果仓库中放有产品,则消费者可以将产品取走消费,否则停止消费并等待,直到仓库中再次放入产品 这是一个线程同步问题,生产者和消费者共享同一个资源,并且生产者和消费者之间相互依赖,互为条件 对于生产者,没有生产产品之前,要通知消费者等待。而生产了产品之后,又需要马上通知消费者消费 对于消费者,在消费之后,要通知生产者已经消费结束,需要继续生产新产品以供消费 在生产者消费者问题中,仅有synchronized是不够的 synchronized可阻止并发更新同一个共享资源,实现了同步 synchronized不能用来实现不同线程之间的消息传递(通信) Java提供了3个方法解决线程之间的通信问题: Obj.wait() 使当前线程等待并释放锁标志, 直到其他线程调用此对象的notify()方法或notifyAll() 方法 Ojb.notify() 唤醒在此对象监视器上等待的单个线程 并放弃此对象上的锁定 Obj.notifyAll() 唤醒在此对象监视器上等待的所有线程 并放弃此对象上的锁定 此三个方法必须在synchronized方法或synchronized块中调用 public class WaitAndNotifyDemo_2 { public static void main(String[] args) { Product product=new Product();//共享同一个共享资源 new Producer(product).start(); //生产者线程 new Consumer(product).start(); //消费者线程 } } //共享的数据:产品 class Product{ private String name; private boolean isProduced=false; //是否已生产 //生产产品 public synchronized void make(String name){ //如果产品还未消费,则生产者等待 if(isProduced){ System.out.println("消费者还未消费,因此生产者停止生产"); try { wait(); // 生产者等待 } catch (InterruptedException e) {} } this.name=name; isProduced = true; // 标记已经生产 notify(); // 通知消费者已经生产,可以消费 System.out.println("生产了产品:" +name+ " 通知消费者消费..."); } //获取产品消费 public synchronized String getProduct(){ // 如果产品还未生产,则消费者等待 if(!isProduced){ try{ System.out.println("生产者还未生产,因此消费者停止消费"); wait(); // 消费者等待 } catch (InterruptedException e) { e.printStackTrace(); } } isProduced = false; // 标记已经消费 notify(); // 通知需要生产 System.out.println("消费者消费了产品" + name + " 通知生产者生产..."); return this.name; } } //生产者线程 class Producer extends Thread{ private Product product; public Producer(Product product){ this.product=product; } public void run(){ String[] strArr={"1","2","3","4","5","6","7"}; for(String str:strArr){ try { Thread.sleep(100); } catch (InterruptedException e) { } product.make(str);// 将产品放入仓库 } } } //消费者线程 class Consumer extends Thread{ private Product product; public Consumer(Product product){ this.product=product; } public void run(){ String str=null; do{ try { Thread.sleep(100); } catch (InterruptedException e) { } str=product.getProduct(); }while(!"7".equals(str)); } }

下载文档,方便阅读与编辑

文档的实际排版效果,会与网站的显示效果略有不同!!

需要 5 金币 [ 分享文档获得金币 ]
0 人已下载

下载文档

相关文档