Java多线程

多线程的目的是最大限度的利用CPU资源

1、进程&线程

1)进程由一个或多个线程组成

2)进程是程序的执行过程(程序就是一段静态的代码段)

3)线程是比进程更小的执行单位,是进程中的“小进程”

4)线程是程序内顺序控制流

5)进程中的线程共享系统分派给进程的内存空间,还有属于自己的内存空间(线程栈)

6)每个线程都有自己的堆栈和程序计数器。你可以把程序计数器设想为用于跟踪线程正在执行的指令。堆栈用于跟踪线程的上下文,上下文是当线程执行到某处时,当前的局部变量的值。

Java中如果我们自己没有定义线程,那么系统就会给我们产生一个线程(主线程,main方法就在主线程上运行),我们的程序都是由线程来执行的。

2、线程的四种可能的状态

1)新建(初始状态)

调用new方法之后,调用start方法之前。在初始状态,可以调用start或stop

2)运行(Runnable)

线程调用了start方法,就转到Runnable状态。线程创建后仅仅占用了内存的资源,在JVM管理的线程中还没有这个线程,此线程必须调用start()方法通知JVM。JVM就知道又有一个新线程排队等候切换了。(所以注意:当线程处于Runnable状态,它也有可能不在运行,因为还有优先级和调度的问题。)

3)中断

四种中断的原因

-JVM将CPU资源从当前线程切换给其他线程,使线程让出了CPU的使用权并处于中断状态

          线程的让步是通过Thread.yield()来实现的。yield()方法的作用是:暂停当前正在执行的线程对象,并执行其他线程。

-线程使用CPU资源期间,执行了sleep方法,使当前线程进入休眠状态

          Thread.sleep(long millis)和Thread.sleep(long millis, int nanos)静态方法强制当前正在执行的线程休眠(暂停执行),以“减慢线程”。当线程睡眠时,它入睡在某个地方,在苏醒之前不会返回到可运行状态。当睡眠时间到期,则返回到可运行状态。

         睡眠的实现:调用静态方法。
            Thread.sleep(123);
         睡眠的位置:为了让其他线程有机会执行,可以将Thread.sleep()的调用放线程run()之内。这样才能保证该线程执行过程中会睡眠。
         注意:
        1、线程睡眠是帮助所有线程获得运行机会的最好方法。
        2、线程睡眠到期自动苏醒,并返回到可运行状态,不是运行状态。sleep()中指定的时间是线程不会运行的最短时间。因此,sleep()方法不能保证该线程睡眠到期后就开始执行。
        3、sleep()是静态方法,只能控制当前正在运行的线程。

-线程使用CPU资源期间,执行了wait方法,使当前线程进入等待状态

-线程使用CPU资源期间,执行某个操作进入阻塞状态,例如I/O请求

4)死亡

线程死亡的原因:

-执行完run()方法中的全部语句,结束run()方法

-线程被强制终止,即强制run()方法结束


5、创建线程的方法

1)继承Thread类,重写run方法

任何继承Thread的JAVA类都可以通过Thread类的start方法建立线程,如果想要运行自己的线程执行函数,那就覆盖Thread类方法。

Thread类下的五个方法:

run():该方法用于线程的执行。你需要重写该方法,以便让线程做特定的工作

start():使线程启动run()方法

stop():与start相反,停止线程的运行

suspend():该方法同stop()方法不同的时,它并没有终止未完成的线程,它仅仅是挂起线程,以后还可以恢复。

resume():该方法重新启动已经挂起的线程

public class ThreadTest
{
	public static void main(String[] args)
	{
		Thread1 th1=new Thread1("first thread");
		Thread2 th2=new Thread2("secong thread");
		System.out.println(th1.getName());
		System.out.println(th2.getName());
		th1.start();
		th2.start();
	}

}

class Thread1 extends Thread
{
public Thread1(String name)
{
	super(name);
}
	@Override
	public void run()
	{
for(int i=0;i<10;i++)
{
	System.out.println("Hello World"+i);
}
	}
	
}

class Thread2 extends Thread
{
	public Thread2(String name){
		super(name);
	}
	@Override
	public void run()
	{
for(int i=0;i<10;i++)
{
	System.out.println("Welcome"+i);
}
	}
}

继承Thread类,我们要重写run方法,因为run方法中此时什么事都没有做。

修改线程名的两种方式:

1)构造方法

2)setName()方法

注意:1)在调用start()方法前后都可以使用setName设置线程名

    2)但在调用start()方法后使用setName修改线程名,会产生不确定性

Thread类的start方法不能多次调用,如调用thread.start()方法,会抛出IllegalThreadStateException异常

2)通过定义实现Runnable接口的类进而实现run方法

1、将实现Runnable接口的类实例化
2、建立一个Thread对象,并将第一步实例化后的对象作为参数传入Thread类的构造方法
3、最后通过Thread类的start方法建立线程

public class MyThread2 implements Runnable
{

	@Override
	public void run()
	{
		// TODO Auto-generated method stub
		for(int i=0;i<10;i++)
        System.out.println("hello world"+i);
	}

}

Thread类也实现了Runnable接口,因此也实现了Runnable接口中的run方法。


6、线程优先级

可以通过设置线程的属性和方法来该改变线程的优先级

1)设置线程的优先级(setPriority)

2) 设置线程名(setName)

3)设置线程类型 (setDaemon)


参考资料:http://www.cnblogs.com/riskyer/p/3263032.html


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值