首页 > 代码库 > 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 多线程