String getName() 返回该线程的名称。
class TestThread { public void run() { while(true) { System.out.println(Thread.currentThread().getName()+" is running"); } } } public class ThreadDemo1 { public static void main(String[] args) { /** * public void run()如果该线程是使用独立的 Runnable 运行对象构造的 * 则调用该 Runnable 对象的 run 方法;否则,该方法不执行任何操作并返回。 */ new TestThread().run(); while(true) { System.out.println("main thread is running"); } } }上面的代码运行后,屏幕不停的打印 main is running,而不是 main thread is running 。对代码修改如下:
class TestThread2 extends Thread { public void run() { while(true) { System.out.println(Thread.currentThread().getName()+" is running"); } } } public class ThreadDemo2 { public static void main(String[] args) { /** * public void start()使该线程开始执行; * Java 虚拟机调用该线程的 run 方法。 */ new TestThread2().start();//run(); while(true) { System.out.println("main thread is running"); } } }
Java单线程与多线程的比较:
1. 可见,在单线程中,main函数必须等到TestThread.run()函数返回后才能继续往下执行。
而在多线程中,main函数调用TestThread.start()方法启动了TestThread.run()函数后,main函数不等待TestThread.run函数返回就继续运行。
2. 要将一段代码在一个新的线程上运行,该代码应该在一个类的run函数中,并且run函数所在类是Thread类的子类。在子类的run函数中高调用想在新线程上运行的程序代码。
3. 启动一个新的线程,不是直接调用Thread子类对象的run方法,而是直接调用Thread子类对象的start(从Thread类中继承的)方法,Thread类对象的start方法将产生一个新的线程,并在该线程上运行该Thread类对象中的run方法。
(2)使用Runnable接口创建多线程 / 实现 Runnable 接口
构造器 public Thread(Runnable target)
Runnable接口:其只有一个run()方法。当使用上述构造器创建线程对象时,行为该方法传递一个实现
Runnable接口的类对象,这样创建的线程将调用那个实现了Runnable接口的类对象中的run()方法作为其运行代码。
public class ThreadDemo3 { public static void main(String[] args) { /* * Thread(Runnable target) * 需要传递一个实现了Runnable接口的类对象 * Runnable接口中只定义了run()方法 */ TestThread3 tt3 = new TestThread3(); Thread t = new Thread(tt3); t.start(); while(true){ System.out.println("main thread is running"); } } } class TestThread3 implements Runnable{ /* * 线程的代码段,当执行start时,线程从此开始执行 */ public void run(){ while(true) { System.out.println(Thread.currentThread().getName()+" is running"); } } }
提示:多个线程去处理一个资源,一个资源只能对应一个对象 ---> 使用Runnable接口方式
public class TicketTest { public static void main(String[] args) { TicketThread tt = new TicketThread(); new Thread(tt).start(); new Thread(tt).start(); new Thread(tt).start(); new Thread(tt).start(); } } class TicketThread implements Runnable{ private int tickets=100; @Override public void run() { for(int i=0;i<1000;i++){ if(tickets>0){ System.out.println(Thread.currentThread().getName()+" selles No." + tickets--); } } } }
多线程的同步
(1)线程的安全性问题:
即使是上面的实现方式中仍然是有安全隐患的,在run方法中故意增加延迟(调用sleep方法),便会显现。
Thread类有如下方法:
public static void sleep(long millis)
在指定的毫秒数内让当前正在执行的线程休眠(暂停执行)
e.g 在上面的卖票例子的示例程序修改如下,便会出现线程同步问题:
public void run() { for(int i=0;i<1000;i++){ if(tickets>0){ Thread.sleep(10); System.out.println(Thread.currentThread().getName()+" selles No." + tickets--); } } }说明:线程的睡眠是可以被打断的,通过Thread.interrupt(),线程的睡眠被打断进入Runnable状态。
class TicketThread implements Runnable { private int tickets = 100; @Override public void run() { sale(); } synchronized void sale() { for (int i = 0; i < 1000; i++) { if (tickets > 0) { try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + " selles No." + tickets--); } } } }
public class X { private final ReentrantLock lock = new ReentrantLock(); //定义需要保证线程安全的方法 public void m(){ //加锁 lock.lock(); try{ //... method body }finally{ //在finally释放锁 lock.unlock(); } } }
class TicketTest5 implements Runnable { private final ReentrantLock lock = new ReentrantLock(); private int tickets = 100; @Override public void run() { for(int i=0;i<1000;i++){ sale(); } } public void sale(){ lock.lock(); if(tickets>0){ try { Thread.sleep(1); System.out.println(Thread.currentThread().getName()+"卖出了第"+tickets-- +"张票"); }catch(Exception e) { e.printStackTrace(); } finally { lock.unlock(); } } } }
原文:http://blog.csdn.net/tao_sun/article/details/20292825