java实现多线程有两种方法
java实现多线程有两种方法:
一种是继承Thread类
如下面例子:
public class TestThread extends Thread { //实现多线程方法一:继承Thread类,并重载run方法 public void run(){ //要将一段代码在一个新的线程上运行,该代码应写在run函数中 while(true){ System.out.println(Thread.currentThread().getName() + "is running..."); } }}public class ThreadDemo2 { public static void main(String[] args) { //启动一个新的线程,不是直接调用Thread类子类对象的run方法, //而是调用Thread类子类对象的start方法,Thread类对象的start方法 //将产生新的线程,并在该线程上运行该Thread类对象中的run方法,根据 //多态性 实际上运行的是Thread子类的run方法 TestThread testThread = new TestThread(); testThread.start(); while(true){ System.out.println("main thread is running..."); } }}
?方法二是:实现接口Runnable中的run函数
如下列所示
//实现多线程方法二:实现Runnable接口,重载run函数,//大多数情况下,如果只想重写 run() 方法,而不重写其他 Thread 方法,//那么应使用 Runnable 接口。这很重要,//因为除非程序员打算修改或增强类的基本行为,否则不应为该类创建子类。public class TestThread implements Runnable { public void run() { // TODO Auto-generated method stub System.out.println(Thread.currentThread().getName() + "is running......"); } } public static void main(String[] args) { // TODO Auto-generated method stub TestThread testThread = new TestThread();//创建TestThread类的一个实例 Thread thread = new Thread(testThread);//创建一个Thread类的实例 thread.start();//使线程进入runnable状态 while(true){ System.out.println("main thread is running..."); } }
2.这两种方法的区别:实现Runnable接口适合多个相同的程序代码访问处理同一资源
如下列所示://四个售票窗口售同一中车票,总共有100张,要求这四个售票多线程进行public class TicketRunnable implements Runnable { private int tickets = 100; public void run() { while(true){ if(tickets > 0){ System.out.println(Thread.currentThread().getName() + " is saling ticket " + tickets--); } } }}public class TicketRunnableDemo { public static void main(String[] args){ //创建了四个线程,每个线程调用了同一各TicketRunnable对象中run方法, //访问的是同一个对象中的变量tickets,从而满足了我们的要求。 //实现Runnable接口适合多个相同的程序代码访问处理同一资源 TicketRunnable ticketrunnable = new TicketRunnable(); new Thread(ticketrunnable).start(); new Thread(ticketrunnable).start(); new Thread(ticketrunnable).start(); new Thread(ticketrunnable).start(); }}而继承继承Thread类,并重载run方法不能达到此目的如下所示:public class TicketThread extends Thread { private int tickets = 100; public void run(){ while(true){ if(tickets>0){ System.out.println(Thread.currentThread().getName() + "is saling ticket " + tickets--); } } }}public class TicketThreadDemo { public static void main(String[] args){ //我们希望的是四个线程共售100,我们创建四个线程 //但结果与我们希望的相反,各个线程各售100张票 new TicketThread().start(); new TicketThread().start(); new TicketThread().start(); new TicketThread().start(); // 如果我们象下面这样写的话,只有一个线程在售票,没有实现四个线程并发售票// TicketThread ticketThread = new TicketThread();// ticketThread.start();// ticketThread.start();// ticketThread.start();// ticketThread.start(); }}
3.后台线程
public class DaemonTest { public static void main(String[] args){ TicketRunnable ticketRunnable = new TicketRunnable(); Thread thread = new Thread(ticketRunnable); thread.setDaemon(true);//将此线程设置为后台线程,当进程中只有后台线程时,进程就会结束 thread.start(); }}
?5. 线程同步
在上面的售票程序中,线程可能是不安全的,
比如我们修改一下:
public class ThreadRunnable implements Runnable{ private int tickets = 100; public void run() { while(true){ if(tickets > 0){ try{ Thread.sleep(10);//使该线程暂停, }catch(Exception e){ System.out.println(e.getMessage()); } System.out.println(Thread.currentThread().getName() + " is saling ticket " + tickets--); } } }}再次测试时,发现可能会打印-1 -2 这样的ticket所以我们要修改一下,使该程序是线程安全的,public class TicketSynch implements Runnable{ private int tickets = 100; String str = new String("");//此对象放在run函数之外 public void run(){ while(true){ synchronized(str){//同步代码块 if(tickets > 0){ try{ Thread.sleep(10); } catch(Exception e){ System.out.println(e.getMessage()); } System.out.println(Thread.currentThread().getName() +" is saling ticket " + tickets--); } } } }}但是 同步以牺牲程序的性能为代价5. 同步函数public class SynchMethod implements Runnable{ private int tickets = 100; public void run(){ while(true){ sale(); } } public synchronized void sale(){ if(tickets > 0){ try{ Thread.sleep(10); }catch(Exception e){ System.out.println(e.getMessage()); } System.out.println(Thread.currentThread().getName() + "is saling ticket " + tickets--); } }} public static void main(String[] args){ //创建了四个线程,每个线程调用了同一各TicketRunnable对象中run方法, //访问的是同一个对象中的变量tickets,从而满足了我们的要求。 //实现Runnable接口适合多个相同的程序代码访问处理同一资源 SynchMethod synchMethod = new SynchMethod(); new Thread(synchMethod).start(); new Thread(synchMethod).start(); new Thread(synchMethod).start(); new Thread(synchMethod).start(); }6.代码块和函数间的同步public class MethodAndBlockSyn implements Runnable{ private int tickets = 100; String str = new String(""); public void run(){ if(str.equals("method")){ while(true){ sale(); } } else{ synchronized(str){//同步代码块 if(tickets > 0){ try{ Thread.sleep(10); } catch(Exception e){ System.out.println(e.getMessage()); } System.out.println(Thread.currentThread().getName() +" is saling ticket " + tickets--); } } } } public synchronized void sale(){ if(tickets > 0){ try{ Thread.sleep(10); }catch(Exception e){ System.out.println(e.getMessage()); } System.out.println(Thread.currentThread().getName() + "is saling ticket " + tickets--); } }} public static void main(String[] args){ MethodAndBlockSyn test = new MethodAndBlockSyn(); new Thread(test).start();// 这个线程调用同步代码块 try{ Thread.sleep(1);//让线程等待100ms 是为了让该线程得到CPU //避免该线程未得到CPU就将str设置为method,从而使此线程也是调用同步函数 }catch(Exception e) { } test.str = new String("method"); new Thread(test).start();//这个线程调用同步函数 }
???