当 Java 虚拟机启动时,通常都会有单个非守护线程(它通常会调用某个指定类的 main 方法)。Java 虚拟机会继续执行线程,直到下列任一情况出现时为止:
· 调用了 Runtime 类的 exit 方法,并且安全管理器允许退出操作发生。
· 非守护线程的所有线程都已停止运行,无论是通过从对 run 方法的调用中返回,还是通过抛出一个传播到 run 方法之外的异常。
创建新执行线程有两种方法。一种方法是将类声明为 Thread 的子类。该子类应重写 Thread 类的 run 方法。接下来可以分配并启动该子类的实例。例如,计算大于某一规定值的质数的线程可以写成:
class PrimeThread extends Thread {
long minPrime;
PrimeThread(long minPrime) {
this.minPrime = minPrime;
}
public void run() {
// compute primes larger than minPrime
. . .
}
}
然后,下列代码会创建并启动一个线程: PrimeThread p = new PrimeThread(143);
p.start();
创建线程的另一种方法是声明实现 Runnable 接口的类。该类然后实现 run 方法。然后可以分配该类的实例,在创建 Thread 时作为一个参数来传递并启动。采用这种风格的同一个例子如下所示:
class PrimeRun implements Runnable {
long minPrime;
PrimeRun(long minPrime) {
this.minPrime = minPrime;
public void run() {
// compute primes larger than minPrime
. . .
}
}
然后,下列代码会创建并启动一个线程:
//普通方法启动线程
PrimeRun p = new PrimeRun(143);
new Thread(p).start();
//使用线程池启动线程
PrimeRun p = new PrimeRun(143);
ExcutorService exec=Excutors.newCachedThreadpool();
Exec.execute(p);
后台线程 使用setDaemon()方法设置,后台线程不是程序不可或缺的部分,当所有非后台线程执行完毕后,程序结束并且会杀死所有的后台线程。
线程的join方法详解:
public class Test extends Thread{
public static void main(String[] args){
Test1 t=new Test1();
t.start();
try{
t.join();//先执行完t线程再执行主线程
}catch(Exception e){
}
for(int i=0;i<10;i++){
System.out.println("test");
}
}
}
class Test1 extends Thread{
public void run(){
for(int i=0;i<10;i++){
System.out.println("test1");
}
}
}
Thread.yield():让其他线程执行 ;Thread.sleep():当前线程休眠,这两个方法都不会释放对象锁。
线程的异常如果逃出了run方法,那么就会向外传播到控制台,所以我们要在run方法中捕获异常
所有对象都自动含有单一的锁,在其对象上调用任意Synchronized方法的时候,这个对象都会被加锁,这时该对象上的其他Synchronized方法只有等到前一个方法调用完毕并释放锁之后才能被调用。
一个任务可以同一个对象中的Synchronized方法,因为这个任务在第一次调用的时候已经获得了对象锁。
Synchronized修饰的方法或者同步块的时候,就锁上对象,但是这里锁仅仅对对象的其他Synchronized方法或者同步块起作用,至于那些非同步的方法,我们还是可以在加锁后继续访问:
如下面这个例子:
public class TestThread{
public static void main(String[] args){
Tt tt=new Tt();
Thread thread=new Thread(tt);
thread.start();
try{
Thread.sleep(1000);
}catch(Exception e){
}
tt.m2();
}
}
class Tt implements Runnable{
public synchronized void m1(){
for(int i=0;i<10;i++){
try{
Thread.sleep(1000);
}catch(Exception e){
}
System.out.println("m1");
}
}
public void m2(){
System.out.println("m2");
}
public void run(){
Tt tt=new Tt();
tt.m1();
}
}
防止任务在共享资源上产生冲突的方法;1.同步 2.根除对变量的共享--线程的本地存储
Sleep,yield不会释放锁,wait会释放锁
只能在同步控制方法或者同步控制块里面调用wait,notify,notifyAll,在非同步方法里面调用的时候可以通过编译,但是运行的时候会出现异常。
最后写了一个死锁小程序:
class Task implements Runnable{
static Object o1=new Object(),o2=new Object();
public int flag=0;
public void run(){
if(flag==1){
synchronized(o1){
System.out.println("flag==1-------Synchronized o1");
try{
Thread.sleep(1000);
}catch(InterruptedException e){
}
synchronized(o2){
System.out.println("flag==1-------Synchronized o2");
}
}
}
if(flag==0){
synchronized(o2){
System.out.println("flag==0-------Synchronized o1");
try{
Thread.sleep(1000);
}catch(InterruptedException e){
}
synchronized(o1){
System.out.println("flag==0-------Synchronized o2");
}
}
}
}
}
public class DeadLock{
public static void main(String[] args){
Task task1=new Task();
Task task2=new Task();
task1.flag=1;
task2.flag=0;
Thread t1=new Thread(task1);
Thread t2=new Thread(task2);
t1.start();
t2.start();
}
}