首页 > 代码库 > java 多线程

java 多线程

1. 后台线程:

   如果在某个线程运行之前调用了setDaemon方法,则该线程就变为后台线程。

   对java程序来说,只要还有一个前台线程在运行,这个进程就不会结束,如果一个进程只有后台线程在运行,这个进程就会结束。

public class TestSetDaemon {    public static void main(String[] args) {        Thread th = new Thread(new ThreadTest());        //th.setDaemon(true);        th.start();    }}class ThreadTest implements Runnable{    public void run(){        while(true){            System.out.println("threadtest is running");        }    }}

2. 联合线程:
thread.join()作用是把thread所对应的线程合并到调用thread.join()语句的线程中。

public class TestJoin {    public static void main(String[] args) {        Thread th=new Thread(new JoinThread());        th.start();        int i=1;        while(true){            i++;            if(i==100)                th.join(10000);            System.out.println("main***************");            Thread.sleep(100);        }    }}class JoinThread implements Runnable{    public void run(){        while(true){                                        Thread.sleep(100);            System.out.println("threadtest is running");        }    }}

3.继承Thread与Runnable接口的区别:
   适合多个相同的程序代码的线程去处理同一资源的情况,把虚拟CPU(线程)同程序的代码、数据有效分离,较好的体现了面向对象的设计思想。

public class ExtendsThread {    public static void main(String[] args) {        Thread th1=new Tick();        Thread th2=new Tick();        th1.start();        th2.start();    }}class Tick extends Thread{    public static int count=100;   //必须是全局    public void run(){        while(count>0){        System.out.println(Thread.currentThread()+"*****"+(count--));    }    }}public class ImplemtRunnable {    public static void main(String[] args) {        Ticket t = new Ticket();        Thread th1 = new Thread(t);        Thread th2 = new Thread(t);        th1.start();        th2.start();    }}class Ticket implements Runnable{    int count=100;    public void run(){        while(count>0){            System.out.println(Thread.currentThread()+"***"+(count--));        }    }}

线程同步:sychronized关键字的原理:任何一个对象都有一个标志位,它有0,1两种状态,开始状态为1,当线程执行到含有sychronized的关键字时就会检查它所带的对象的标志位是1还是0,如果标志位为1,则能继续向下执行,同时将对象的标志位置0。如果对象的标志位为0,线程就会阻塞,将它放在该对象的阻塞队列中,一直等到该标志位为1,才从该对象的阻塞队列中取出一个等待的线程,继续执行。我们的线程在加上sychronized关键字后,并不能决定CPU的调度问题,只是在标志位为0时,不能继续执行,这样可以保证在一段时间内,该代码段只被一个线程访问,从而保证线程安全。

public void run(){    while(true){    if(count>0){//要保证这条语句的原子性        try {Thread.sleep(100);} catch (InterruptedException e) {}        System.out.println(Thread.currentThread()+"*******"+(count--));    }   }}//同步代码块class Ticket implements Runnable{    int count=100;    String str=new String();   //同步对象定义不能放在run方法中,因为每个对象在调用run方法时都会产生一个新的同步对象,并不是同一个监视器对象    public void run(){         while(true){             synchronized (str) {              if(count>0){//通过synchronized保证这条语句的原子性              try {Thread.sleep(100);} catch (InterruptedException e) {}              System.out.println(Thread.currentThread()+"****"+(count--));         }    }     }}    //同步方法class Ticket implements Runnable{    int count=100;    public void run(){         while(true){        this.sale();        }    }    public synchronized void sale(){        if(count>0){//要保证这条语句的原子性        try {Thread.sleep(100);} catch (InterruptedException e) {}        System.out.println(Thread.currentThread()+"***"+(count--));       }    }}//方法与代码块同步public class ImplemtRunnable {    public static void main(String[] args) throws InterruptedException {        Ticket t = new Ticket();        Thread th1 = new Thread(t);        th1.start();        Thread.sleep(100);  //确保在th2运行之前th1已经启动        Thread th2 = new Thread(t);        t.str=new String("methord");        th2.start();    }}  class Ticket implements Runnable{    int count=100;    String str=new String();    public void run(){        if(str.equals("methord")){        while(true){            this.sale();        }       }else{        while(true){            synchronized (this) {            if(count>0){//要保证这条语句的原子性                try {Thread.sleep(100);} catch () {}                    System.out.println(Thread.currentThread().getName()+"******block*****"+(count--));            }        }                    }    }        }    public synchronized void sale(){        if(count>0){//要保证这条语句的原子性            try {Thread.sleep(100);} catch (InterruptedException e) {}            System.out.println(Thread.currentThread()+"*******methord*****"+(count--));        }    }}

线程死锁:线程A得到监视器1,而同时请求监视器2;线程B得到了监视器2,而同时请求监视器1
synchronized(str1){                          synchronized(str2){   

  synchronized(str2){                            synchronized(str1){  

  }                                                       }

}                                                      }

多个线程访问同一数据时就会发生线程安全问题,就必须实现对原子性的操作进行同步操作(要使用同一个监视器)。

public void push(char c)

{  //两个线程同时访问时  线程1进入push方法时,index=2,线程1将c放在data[2]中,还没来得急进行index++。CPU此时又调度线程2执行,此时index仍为2,线程2又将数据放在data[2]中,就会导致在此位置放置了两次数据,而index=3中没有数据。

  data[index]=c;  index++;

}

java 多线程