---------- android培训 java培训 期待与您交流!------------
个Java程序都有一个默认的主线程。Java程序总是从主类的main方法开始执行。当JVM加载代码,发现main方法后就启动一个线程,这个线程就称作"主线程",该线程负责执行main方法。在main方法中再创建的线程就是其他线程。
如果main方法中没有创建其他线程,那么当main方法返回时JVM就会结束Java应用程序。但如果main方法中创建了其他线程,那么JVM就要在主线程和其他线程之间轮流切换,保证每个线程都有机会使用CPU资源,main方法返回(主线程结束)JVM也不会结束,要一直等到该程序所有线程全部结束才结束Java程序,另外一种情况是:程序中调用了Runtime类的exit方法,并且安全管理器允许退出操作发生。这时JVM也会结束该程序。
线程的状态与生命周期:
当一个Thread类或其子类对象被声明并创建,新生的线程对象就处于新建状态(此时它已经有了内存空间和其他资源)。
线程已经创建就具备了运行的条件,一旦轮到它来享用CPU资源时,即JVM将CPU使用权切换给该线程时,此线程就可以脱离创建它的主线程独立开始自己的生命周期了。
线程创建后仅仅是占有了内存资源,在JVM管理的线程中还没有这个线程,此线程必须调用start()方法(从父类继承)通知JVM,这样JVM就知道又有一个新的线程排队等候切换。
Java中实现多线程有两种方法:
1、继承Thread类,覆盖run()方法:使用Thread子类创建线程的优点是可以在子类中增加新的成员变量或方法,使线程具有某种属性或功能。但Java不支持多继承,Thread类的子类不能再扩展其他的类。
2、实现Runnable接口:用Thread类直接创建线程对象,使用构造函数Thread(Runnable target)(参数target是一个Runnable接口),创建线程对象时必须向构造方法参数传递一个实现Runnable接口类的实例,该实例对象称作所创线程的目标对象。当线程调用start()方法,一旦轮到它使用CPU资源,目标对象自动调用接口中的run()方法(接口回调)。
class threadTest extends Thread
{
public void run()
{
System.out.println("threadTest run");
}
}
class threadTest1 implements Runnable
{
public void run()
{
System.out.println("threadTest1 run");
}
}
线程间可以共享相同的内存单元(包括代码和数据),并利用这些共享单元来实现数据交换、实时通信与必要的同步操作。对于Thread(Runnable target)创建的使用同一目标对象的线程,可以共享该目标对象的成员变量和方法。
比如一下操作可以在两个线程间交换数据
public class multithread {
public static void main(String [] args)
{
info i = new info();
new threadTest(i,"李磊",23).start();
new Thread(new threadTest1(i)).start();
}
}
//一个信息类,用来让threadTest和threadTest1交换数据
class info
{
private String name;
private int age;
/**
* @return the name
*/
public String getName() {
return name;
}
/**
* @param name the name to set
*/
public void setName(String name) {
this.name = name;
}
/**
* @return the age
*/
public int getAge() {
return age;
}
/**
* @param age the age to set
*/
public void setAge(int age) {
this.age = age;
}
public String toString()
{
return "name="+name+", age="+age;
}
}
//继承Thread覆盖run()
class threadTest extends Thread
{
private info in;
private String name;
private int age;
threadTest(info in,String name,int age)
{
this.in = in;
this.name = name;
this.age = age;
}
public void run()
{
in.setName(name);
in.setAge(age);
}
}
//实现Runnable接口覆盖run()
class threadTest1 implements Runnable
{
private info in;
threadTest1(info in)
{
this.in = in;
}
public void run()
{
String str = in.toString();
System.out.println(str);
}
}
start():线程调用该方法将启动线程,从新建态进入就绪队列,一旦享用CPU资源就可以脱离创建它的线程,独立开始自己的生命周期。
new threadTest().start();
new threadTest1().run();
sleep(int millsecond):有时,优先级高的线程需要优先级低的线程做一些工作来配合它,此时为让优先级高的线程让出CPU资源,使得优先级低的线程有机会运行,线程在休眠中如果被打断就会报异常,所以sleep方法需要try语句。
currentThread():是Thread类的类方法,可以用类名调用,返回当前正在使用CPU资源的线程。
interrupt():当线程调用sleep()方法处于休眠状态,一个占有CPU资源的线程可以让休眠的线程调用interrupt()方法"吵醒"自己,即导致线程发生IllegalThreadStateException异常,从而结束休眠,重新排队等待CPU资源。
线程同步: 当两个或多个线程同时访问一个变量,并且一个线程需要修改这个变量时,应对这样的问题进行处理,否则可能发生混乱。
要处理线程同步,可以把修改数据的方法用关键字synchronized修饰。一个方法使用synchronized修饰,当一个线程A使用这个方法时,其他线程想使用该方法时就必须等待,直到线程A使用完该方法。所谓同步就是多个线程都需要使用一个synchronized修饰的方法。
做一个多线程售票的例子:
public class multithread {
public static void main(String [] args)
{
ticket t = new ticket();
new Thread(t).start();
new Thread(t).start();
new Thread(t).start();
new Thread(t).start();
}
}
//实现Runnable接口的方式创建线程
class ticket implements Runnable
{
private static int num = 10;
public void run()
{
while(num>0)
{
System.out.println(Thread.currentThread()+":"+ num--);
}
}
}
打印结果为:
守护线程:
线程默认是非守护线程,非守护线程也称用户线程,一个线程调用setDaemon(boolean on)方法可以将自己设置成一个守护(Daemon)线程,如:
thread.setDaemon(true);
一个线程必须在自己运行之前设置自己是否是守护线程。守护线程是当程序中所有用户线程都已结束运行时即使守护线程的run()方法还有需要执行的语句,守护线程也会立刻结束运行。因此守护线程用于做一些不是很严格的工作,当线程随时结束时不会产生什么不良后果。
---------- android培训 java培训 期待与您交流!------------
详情请点击:http://edu.csdn.net/