A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 枫听月下 初级黑马   /  2014-9-4 20:48  /  907 人查看  /  0 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

 ------- <a  target="blank">android培训</a>、<a  target="blank">java培训</a>、期待与您交流! ----------

----------- android培训java培训、java学习型技术博客、期待与您交流! ------------

在单CPU的硬件平台下,某一时刻只能有一个线程在运行,线程是由操作系统调度的。

启动一个线程不能直接调用run()方法,这样不会创建一个新的线程,只是简单的在当前线程中执行了run()方法,
而应该调用start()方法,这样就会创建一个新的线程,在这个新的线程上执行run()方法上的代码。
当run()方法执行完后,线程也就相应的结束,我们可以通过控制run()方法中循环的条件来控制线程的结束。
(一个进程里面的多个线程都是无规律的交替运行)
Thread类中的setDaemon(true)设置一个线程为后台线程,该方法必须在线程启动之前调用,也就是在调用start()方法之前调用。
如果一个进程中只有后台线程在运行,这个进程就会结束。
thread1.join()的作用是把thread1所对应的线程合并到调用thread1.join()的线程中。
yield()方法可以让当前正在运行的线程对象临时暂停,让别的线程运行。
sleep(...)方法可以让当前正在运行的线程进入睡眠状态。
获取和更改线程的优先级分别用Thread对象的getPriority()方法和setPriority(int newPriority)方法。线程的默认优先级的值是5。
创建一个线程类有两种方法:
1,直接继承Thread类;
2, 实现Runnable接口,然后用new Thread(实现Runnable接口的类的对象)来产生一个线程类。
使用Runnable接口创建多线程,适合多个相同程序代码的线程去处理同一份资源的情况。还可以避免由于java的单继承特性带来的局限。
事实上,几乎所有的多线程应用都可用Runnable接口方式。
每个线程都会有一个运行的时间片,都会有开始和时间片到期的时候。
所以我们要注意了:一个线程的时间片到期的时候,此线程有可能执行到程序的任何一个位置而被暂停,并没有完全执行完一个原子性的模块,
然后就进入时间片的轮换,这样就导致多线程的运行结果不可意料。此时我们就需要对线程进行同步处理。
线程同步关键字是:synchronized
同步代码块放在如下的大括号中:
synchronized(obj){     //用于synchronized的obj叫lock旗标(锁旗标),可以是任何对象,我们通常称之为同步对象或者监视器对象。
}
同步方法只须在方法前加synchronized关键字修饰即可。
同步非静态方法的监视器是this,而同步静态方法的监视器是当前所在的类的Class对象。
只要使用相同的同步对象(监视器),synchronized方法和synchronized代码块也可以实现同步。
在编写多线程同步的时候一定要注意避免死锁的发生。
String str1 = "";
String str2 = "";
while(true) {
synchronized(str1) {
  ...
  synchronized(str2){
   ...
  }
  ...
}
}
while(true) {
synchronized(str2) {
  ...
  synchronized(str1){
   ...
  }
  ...
}
}
如果上面的两个while块里面的代码分别由两个线程执行,那么就形成了死锁。
我们在编写线程安全的程序代码的时候也必须防止一个线程对共享的数据仅仅做了部分的操作的时候,这个线程就结束了,这种情况下就会破坏数据的一致性。
要实现同步的线程所检查的监视器对象必须是同一个对象,才能保证线程的同步。
不同的类中的方法或者语句块也可以实现同步,只要是同一个监视器对象就可以了。
多线程编程里面的run()方法里面通常都是一个while循环程序。
Object类里面有几个方法是用于线程通信的:wait(),notify(),notifyAll()。由于任何对象都可以作为监视器对象,所以任何对象都可以调用这几个方法。
但是这些方法只能在被synchronized修饰的方法或者代码块中调用。
每个对象除了有一个锁旗标之外,还有一个线程等待队列(wait set),一个对象刚创建的时候,它的等待队列是空的。
如果一个线程里面有while循环,我们可以设置一个boolean flag变量作为while的循环条件,while(flag),
当我们需要结束这个线程的时候就可以在另外一个线程中将这个flag设置为false即可。
但是有时候我们还需要结合interrupt()方法来结束一个线程,见如下例子:
package com.heima.exam;
class StopThreadTest {
public static void main(String[] args) {
  
  ThreadInStop t1 = new ThreadInStop();
  t1.start();
  int index = 0;
  
  while(true) {
   if(index++ == 500){
    t1.stopThread();
    t1.interrupt();
    break;
   }
   System.out.println(Thread.currentThread().getName());
  }
  System.out.println("main() exit");
}
}
class ThreadInStop extends Thread {

private boolean bStop = false;

public synchronized void run() {
  
  while(!bStop) {
   try {
    wait();
   } catch(InterruptedException e) {
    if(bStop) {
     return;
    }
   }
   System.out.println(getName());
  }
}

public void stopThread() {
  bStop = true;
}
}

----------------------- android培训java培训、java学习型技术博客、期待与您交流! ----------------------


0 个回复

您需要登录后才可以回帖 登录 | 加入黑马