什么是线程 线程同步的方法
有时候,线程也称作轻量级进程。就象进程一样,线程在程序中是独立的、并发的执行路径,每个线程有它自己的堆栈、自己的程序计数器和自己的局部变量。但是,与分隔的进程相比,进程中的线程之间的隔离程度要小。它们共享内存、文件句柄和其它每个进程应有的状态。
进程可以支持多个线程,它们看似同时执行,但互相之间并不同步。一个进程中的多个线程共享相同的内存地址空间,这就意味着它们可以访问相同的变量和对象,而且它们从同一堆中分配对象。
尽管这让线程之间共享信息变得更容易,但您必须小心,确保它们不会妨碍同一进程里的其它线程。
每个 Java 程序都至少有一个线程 — 主线程。当一个 Java 程序启动时,JVM 会创建主线程,并在该线程中调用程序的main() 方法。
JVM 还创建了其它线程,您通常都看不到它们 — 例如,与垃圾收集、对象终止和其它 JVM内务处理任务相关的线程。其它工具也创建线程,如 AWT(抽象窗口工具箱(Abstract Windowing Toolkit))或Swing UI 工具箱、servlet 容器、应用程序服务器和 RMI(远程方法调用(RemoteMethodInvocation))。
多余的废话就不写那么多了,现在开始介绍一些实质性的东西.
为了确保可以在线程之间以受控方式共享数据,JAVA语言提供了两个关键字是很重要的,他们就是:synchronized 和volatile,所以在学习之前,这两个键字的用法一定要搞清楚.
Synchronized 有两个重要含义:它确保了一次只有一个线程可以执行代码的受保护部分(互斥,mutual exclusion或者说 mutex),而且它确保了一个线程更改的数据对于其它线程是可见的(更改的可见性)。
如果没有同步,数据很容易就处于不一致状态。例如,如果一个线程正在更新两个相关值(比如,粒子的位置和速率),而另一个线程正在读取这两个值,有可能在第一个线程只写了一个值,还没有写另一个值的时候,调度第二个线程运行,这样它就会看到一个旧值和一个新值。同步让我们可以定义必须原子地运行的代码块,这样对于其他线程而言,它们要么都执行,要么都不执行。
Volatile 比同步更简单,只适合于控制对基本变量(整数、布尔变量等)的单个实例的访问。当一个变量被声明成volatile,任何对该变量的写操作都会绕过高速缓存,直接写入主内存,而任何对该变量的读取也都绕过高速缓存,直接取自主内存。这表示所有线程在任何时候看到的volatile 变量值都相同。这两个关键字的具体用法,我会在下一篇文章里面提到.
再介绍一个概念,java锁. 每个 Java 对象都有一个相关的锁。同一时间只能有一个线程持有 Java锁。当线程进入synchronized代码块时,线程会阻塞并等待,直到锁可用,当它可用时,就会获得这个锁,然后执行代码块。当控制退出受保护的代码块时,即到达了代码块末尾或者抛出了没有在synchronized 块中捕获的异常时,它就会释放该锁。
好了,下面讨论一下如何建立线程,有关线程的生命,
在 Java 程序中创建线程有几种方法。每个 Java 程序至少包含一个线程:主线程。其它线程都是通过 Thread构造器或实例化继承类 Thread 的类来创建的。在一个线程对新线程的 Thread 对象调用 start()方法之前,这个新线程并没有真正开始执行。
Thread对象在其线程真正启动之前就已经存在了,而且其线程退出之后仍然存在。这可以让您控制或获取关于已创建的线程的信息,即使线程还没有启动或已经完成了。
通常在构造器中通过 start()启动线程并不是好主意。这样做,会把部分构造的对象暴露给新的线程。如果对象拥有一个线程,那么它应该提供一个启动该线程的 start()或 init() 方法,而不是从构造器中启动它。
线程会以以下三种方式之一结束:
· 线程到达其 run() 方法的末尾。
· 线程抛出一个未捕获到的 Exception 或 Error。
· 另一个线程调用一个弃用的 stop()方法。弃用是指这些方法仍然存在,但是您不应该在新代码中使用它们,并且应该尽量从现有代码中除去它们。
当 Java 程序中的所有线程都完成时,程序就退出了。
Thread API 包含了等待另一个线程完成的方法:join() 方法。当调用 Thread.join()时,调用线程将阻塞,直到目标线程完成为止。
Thread.join()通常由使用线程的程序使用,以将大问题划分成许多小问题,每个小问题分配一个线程。本章结尾处的示例创建了十个线程,启动它们,然后使用Thread.join() 等待它们全部完成。
Thread API 包含了等待另一个线程完成的方法:join() 方法。当调用 Thread.join()时,调用线程将阻塞,直到目标线程完成为止。Thread.join()通常由使用线程的程序使用,以将大问题划分成许多小问题,每个小问题分配一个线程。我会在后面附上示例代码,一个程序创建了十个线程,启动它们,然后使用Thread.join() 等待它们全部完成。
线程的调度是具有不确定性的,下面这个实例代码就能说明这一点.
public class TwoThreads {
public static class Thread1 extends Thread {
public void run() {
System.out.println("A");
System.out.println("B");
}
}
public static class Thread2 extends Thread {
public void run() {
System.out.println("1");
System.out.println("2");
}
}
public static void main(String[] args) {
new Thread1().start();
new Thread2().start();
}
}
谁能知道会打印出什么内容呢?谁也不知道,因为没有人知道执行的顺序,可能是一下的结果:
· 1 2 A B
· 1 A 2 B
· 1 A B 2
· A 1 2 B
· A 1 B 2
· A B 1 2
不仅不同机器之间的结果可能不同,而且在同一机器上多次运行同一程序也可能生成不同结果。永远不要假设一个线程会在另一个线程之前执行某些操作,除非您已经使用了同步以强制一个特定的执行顺序。
Thread API 包含了一个 sleep()方法,它将使当前线程进入等待状态,直到过了一段指定时间,或者直到另一个线程对当前线程的 Thread 对象调用了Thread.interrupt(),从而中断了线程。当过了指定时间后,线程又将变成可运行的,并且回到调度程序的可运行线程队列中。
如果线程是由对 Thread.interrupt()的调用而中断的,那么休眠的线程会抛出异常InterruptedException,这样线程就知道它是由中断唤醒的,就不必查看计时器是否过期。
Thread.yield() 方法就象 Thread.sleep()一样,但它并不引起休眠,而只是暂停当前线程片刻,这样其它线程就可以运行了。在大多数实现中,当较高优先级的线程调用Thread.yield() 时,较低优先级的线程就不会运行。
我们提到过当 Java 程序的所有线程都完成时,该程序就退出,但这并不完全正确。隐藏的系统线程,如垃圾收集线程和由 JVM创建的其它线程会怎么样?我们没有办法停止这些线程。如果那些线程正在运行,那么 Java 程序怎么退出呢?
这些系统线程称作守护程序线程。Java 程序实际上是在它的所有非守护程序线程完成后退出的。
任何线程都可以变成守护程序线程。可以通过调用 Thread.setDaemon()方法来指明某个线程是守护程序线程。您也许想要使用守护程序线程作为在程序中创建的后台线程,如计时器线程或其它延迟的事件线程,只有当其它非守护程序线程正在运行时,这些线程才有用。
在这个示例中,TenThreads显示了一个创建了十个线程的程序,每个线程都执行一部分工作。该程序等待所有线程全部完成,然后收集结果。
public class TenThreads {
private static class WorkerThread extends Thread {
int max = Integer.MIN_VALUE;
int[] ourArray;
public WorkerThread(int[] ourArray) {
this.ourArray = ourArray;
}
// Find the maximum value in our particular piece of thearray
public void run() {
for (int i = 0; i < ourArray.length; i++)
max = Math.max(max, ourArray);
}
public int getMax() {
return max;
}
}
public static void main(String[] args) {
WorkerThread[] threads = new WorkerThread[10];
int[][] bigMatrix = getBigHairyMatrix();
int max = Integer.MIN_VALUE;
// Give each thread a slice of the matrix to work with
for (int i=0; i < 10; i++) {
threads = newWorkerThread(bigMatrix);
threads.start();
}
// Wait for each thread to finish
try {
for (int i=0; i < 10; i++) {
threads.join();
max = Math.max(max, threads.getMax());
}
}
catch (InterruptedException e) {
// fall through
}
System.out.println("Maximum value was " + max);
}
staticint[][]getBigHairyMatrix()
{
int[][]matrix=newint[10][10];
for(inti=0;i<10;i++)
for(intj=0;j<10;j++)
{
matrix[j]=(int)(Math.random()*1000);
}
returnmatrix;
}
}
总结几句: 线程是通过实例化 Thread 对象或实例化继承 Thread 的对象来创建的,但在对新的 Thread 对象调用start() 方法之前,这个线程并没有开始执行。当线程运行到其 run()方法的末尾或抛出未经处理的异常时,它们就结束了。
sleep() 方法可以用于等待一段特定时间;而 join()方法可能用于等到另一个线程完成。
更多阅读
什么是仪器减肥。 最有效的减肥仪器
什么是仪器减肥。——简介仪器减肥是最适合怕苦怕累的懒人了。什么是仪器减肥。——方法/步骤仪器减肥的原理: 有些美容院推荐一些减肥仪器,有通过真空吸盘吸住脂肪堆积处,低电流慢慢按摩、振动,帮助肌肉运动,
什么是参公单位 公务员考试的参公单位
公务员考试的参公单位,或参照管理单位:什么是参公单位——步骤/方法什么是参公单位 1、全称为:参照公务员法管理事业单位。是政府委托或受权具有行政执法能力的单位。是事业单位的一种,单位的管理制度参照公务员管理,但人员属于事业编制,
网上有什么兼职可以做?网上赚钱的方法 网上赚钱的兼职项目
网上有什么兼职可以做?网上赚钱的方法——简介在家闲着有些空闲时间,小编都会到网上去找一些兼职工作,赚赚小钱买点衣服什么的,其实还是不错的。但是小编在这里提醒大家了,网上打兼职广告的很多,记住千万不要轻信那些福利好,能快速发财的项
什么是丝光棉? 丝光棉的成分是什么
1、 什么是双丝光棉?双丝光是指纱线经过丝光处理后织成布,再将布进行丝光处理,那么双丝光棉即为在纱线染色和后整理步骤中均进行丝光处理的全棉。以棉为原料,经精纺制成高织纱,再经烧毛、丝光等特殊的加工工序,制成光洁亮丽、柔软抗皱的
什么是威客?威客的起源与发展? 罗马法的起源与发展
一.什么是威客模式?威客模式是对网络互动问答类网站的概括性称呼,它的定义是:用户通过互联网上的互动问答平台使个人的知识,智慧,技能体现价值特别是经济价值的一种模式.威客的英文是Witkey(wit智慧、key钥匙)。在网络时代,凭借自己的创造