java的多线程机制上

Java多线程基础与实践
本文详细介绍了Java多线程的概念、创建方法、优先级设置、生命周期、状态转换、休眠、让步、插队等核心知识点,并通过示例代码进行实践演示。
一、多线程概述
package com.laobi.day12;

public class ThreadTest01 {
	/**
	 * 进程:正在进行中的程序(直译)
	 *      
	 * 线程:就是进程中一个程序执行的控制单元(执行路径)
	 *      一个进程中可以多执行路径,称之为多线程
	 *      
	 * 一个进程中至少要有一个线程
	 * 
	 * 开启多个线程是为了同时运行多部分代码
	 * 
	 * 每一个线程都有自己运行的内容。这个内容可以称为线程要执行的任务
	 * 
	 * 多线程的好处:解决了多部分同时运行的问题
	 * 多线程的弊端:线程太多会导致效率的降低
	 * 
	 * 其实应用程序的执行都是cpu在做着快速的切换完成的。这个切换时随机的。
	 * 
	 * jvn启动时就启动了多个线程,至少有两个线程可以分析出来的
	 * 1、执行main函数的线程
	 *    该线程的任务代码都定义在main函数中
	 * 2、负责垃圾回收的线程
	 * 
	 * 
	 * @param artcool
	 */
	public static void main(String[] args) {
		Demo d1 = new Demo("旺财");  //主线程运行示例
		Demo d2 = new Demo("小强");
		d1.show();
		d2.show();
//		new Demo();      jvm线程演示
//		System.gc();
		System.out.println("diu");
	}

}
class Demo
{
	private String name;
	
	public Demo(String name) {
		super();
		this.name = name;
	}

	public void show()
	{
		for(int x=0;x<10;x++)
		{
			for(int y=0;y<999999999;y++){}
		System.out.println("demo 走"+name+"..."+x);
		}
		}
}


二、创建线程

package com.laobi.day12;

public class ThreadTest02 {
	/**
	 * 如何创建一个线程呢?
	 * 创建线程方式一:继承Thread类
	 * 
	 * 步骤:
	 * 1、定义一个类继承Thread类。
	 * 
	 * 2、覆盖Thread类中的run方法。
	 * 
	 * 3、直接创建Thread的子类对象
	 * 4、调用start方法开启线程并调用线程的任务run方法执行
	 * 
	 * 可以通过Thread的getName获取线程的名称  Thread——编号
	 * 
	 * 主线程的名字就是main
	 * @param args
	 */
	public static void main(String[] args) {
		/*创建线程的目的是为了开启一条执行路径,去运行指定的代码和其他代码实现同时运行
		而运行的指定代码就是这个执行路径的主任务
		jvm创建的主线程的任务都定义在了主函数中
		而自定义的线程它的任务在哪?
		Thread类用于描述线程,线程是需要任务的。所以Thread类也对任务的描述
		这个任务就是通过Thread类中的run方法来体现。也就是说,run方法就是封装自定义线程运行任务的函数
		
		run方法中定义就是线程要运行的代码任务
		
		开启线程是为了运行指定代码,所以只有继承Thread类,并复写run方法
*/		
//		Thread t1 = new Thread();
		Demo2 d1 = new Demo2("jack");
		Demo2 d2 = new Demo2("tom");
		d1.start();
		d2.start();
		
	}

}
class Demo2 extends Thread
{
	private String name;
	Demo2(String name)
	{
		this.name = name;
	}
	public void run()
	{
		show();
	}
	public void show()
	{
		for(int x=0;x<10;x++)
		{
			for(int y=0;y<999999;y++)
			{
			}
			System.out.println(name+"...."+x+"..."+Thread.currentThread().getName());
		}
	}
}


三、Thread类的基本获取和设置方法

1)获取线程名字
  
  Thread类中方法  String getName()

  在一个不是Thread子类中获取名字:
  Thread类中静态方法
     static Thread currentThread()
  返回正在运行的,当前线程对象  Thread类对象
  继续使用线程对象的 getName()获取线程的名字
  
  
  Thread类的方法 void setName(String name)设置线程名
  Thread(String name) 用的是Thread类构造方法
  子类使用super访问父类构造器
  
  
  在Thread子类中,获取线程名字,直接使用父类方法getName()
  在不是Thread子类中,通用代码,Thread.currentThread().getName()
四、线程的优先级的获取和设置
  
  Thread类方法getPriority() 获取到优先级
  Thread类方法setPriority(int t) 设置优先级

package com.test.xiancheng;

public class Test07 {
	/**
	 *线程的生命周期及状态转换
	 *1、新建状态(new)
	 *   创建一个线程对象后,该线程对象就处于新建状态,此时它不能运行,和其他Java对象
	 *   一样,仅仅由Java虚拟机为其分配了内存,没有表现出任何线程的动态特征
	 *2、就绪状态(runnable)
	 *   当线程对象调用了Start()方法后,线程就进入就绪状态了。
	 *   此时它只是具备了运行条件,能否获得cpu的使用权开始运行,还需要等待系统的调度
	 *3、运行状态(running)
	 *   如果出就绪状态的线程获得了cpu的使用权,开始执行run()方法中的线程执行体,则该线程处于运行状态。
	 *4、阻塞状态(blocked)
	 *   一个正在执行的线程在某些特殊情况下,如执行耗时的输入/输出操作时,会放弃cpu使用权,进入阻塞状态。
	 *   阻塞就不能进入阻塞状态后,就不能进入排队队列。
	 *   例举一下线程由运行状态转换成阻塞状态的原因
	 *   a、当线程试图获取某个对象的同步锁时,如果该锁被其他线程所持有,则当前线程会进入阻塞状态,
	 *      如果想从阻塞状态进入就绪状态必须获得其他线程所持有的锁
	 *   b、当线程调用了一个阻塞式的io方法时,该线程就会进入阻塞状态,如果想进入就绪状态就必须要等到这个阻塞的
	 *      io方法返回
	 *   c、当线程调用了某个对象的wait()时,也会使线程进入阻塞状态,如果想进入就绪状态就需要使用
	 *      notify()方法唤醒该线程
	 *   d、当线程调用了Thread的sleep(long mills)方法时,也会使线程进入阻塞状态,在这种情况下
	 *      只需等到线程的睡眠时间到了以后,线程就会自动进入就绪状态
	 *   f、当在一个线程中调用另一个线程的join()方法时,会使当前线程进入阻塞状态,在这种情况下,需要等到
	 *      需要等到新加入的线程运行结束后才会结束阻塞状态,进入就绪状态
	 *   线程从阻塞状态只能进入就绪状态
	 *5、死亡状态(Terminated)
	 *    线程的run()方法正常执行完毕或者线程抛出一个未捕获的异常(Exception)、错误(Error),线程
	 *    就会进入死亡状态。一旦进入死亡状态I,线程将不再拥有运行的资格,也不能再转换到其他状态
	 *
	 *
	 *线程的调度:分别是分时调度模型和抢占式调度模型
	 *分时调度:让所用的线程轮流获得cpu的使用权,并且平均分配cpu的时间片
	 *抢占式调度:让可运行池中优先级高的线程优先占用cpu,而对优先级相同的
	 *          线程,随机选择一个线程占用cpu,当它失去cpu的使用权后,
	 *          再随机选择其他线程获取cpu使用权。
	 *1、线程的优先级:
	 *   如果需要对线程进行调度,最直接的方式就是设置线程的优先级
	 *2、线程休眠:
	 *   使正在执行的线程暂停,将cpu让给别的线程,这是可以使用sleep(),该方法可以让当前正在执行
	 *   的线程暂停一段时间,进入休眠等待状态。
	 *3、线程让步:
	 *   可以通过yield()方法来实现,该方法和sleep有点相似,都可以让正在运行的线程暂停,
	 *   区别在于yield()方法不会阻塞线程,他只是将线程转换成就绪状态,让系统调度器重新调度一次
	 *4、线程插队:
	 *   当在某个线程中调用其他线程的join()方法时,调用的线程将被阻塞,直到
	 *   被join()方法加入的线程执行完成后他才会继续运行
	 *   
	 *       
	 * 多线程同步:
	 * 1、线程安全
	 * 2、线程同步方法
	 * 3、同步方法:当把共享资源的操作放在synchronized定义的区域内时,便为这些操作加了同步锁
	 *              在方法前面同样可以使用synchronized关键字来修饰,被修饰的方法为同步方法,它能实现
	 *              和同步代码块同样的功能。被synchronized修饰的方法在某一时刻只允许一个线程访问
	 *              ,访问该方法的其他线程都会被阻塞,直到当前线程访问完毕后,其他线程才有机会执行方法
	 *
	 */
	public static void main(String[] args) {
		Thread minPriorty = new Thread(new MinProirty(),"优先级较低的线程");
		Thread maxPriorty = new Thread(new MaxPriorty(),"优先级较高的线程");
		minPriorty.setPriority(Thread.MIN_PRIORITY);
		maxPriorty.setPriority(10);
		maxPriorty.start();
		minPriorty.start();
	}

}
class MaxPriorty implements Runnable
{
	public void run()
	{
		for(int i=0;i<=10;i++)
		{
			System.out.println(Thread.currentThread().getName()+"正在输出:"+i);
		}
	}
}
class MinProirty implements Runnable
{
	public void run()
	{
		for(int i=0;i<=10;i++)
		{
			System.out.println(Thread.currentThread().getName()+"正在输出:"+i);
		}
	}
}


五、线程休眠

package com.test.xiancheng;

public class XCxiumian {
	/**
	 * 线程休眠:
	 *   使正在执行的线程暂停,将cpu让给别的线程,这是可以使用sleep(),该方法可以让当前正在执行
	 *   的线程暂停一段时间,进入休眠等待状态。
	 * @throws Exception 
	 */
	public static void main(String[] args) throws Exception {
		new Thread(new SleepThread()).start();
		for(int i=1;i<=10;i++)
		{
			if(i==5)
			{
				Thread.sleep(2000);
			}
			System.out.println("主线程正在输出:"+i);
			Thread.sleep(500);
		}
	}

}
class SleepThread implements Runnable
{
	public void run()
	{
		for(int i=1;i<=10;i++)
		{
			if(i==3)
			{
				try
				{
					Thread.sleep(2000);
				}
				catch(InterruptedException e)
				{
					e.printStackTrace();
				}
			}
			System.out.println("线程一正在输出:"+i);
			try
			{
				Thread.sleep(500);
			}
			catch(Exception e)
			{
				e.printStackTrace();
			}
		}
	}
}



五、线程让步

package com.test.xiancheng;

public class XCrangbu {
	/**
	 * 线程让步:
	 *   可以通过yield()方法来实现,该方法和sleep有点相似,都可以让正在运行的线程暂停,
	 *   区别在于yield()方法不会阻塞线程,他只是将线程转换成就绪状态,让系统调度器重新调度一次
	 *    
	 */
	public static void main(String[] args) {
		Thread t1 = new YieldThread("线程A");
		Thread t2 = new YieldThread("线程B");
		t1.start();
		t2.start();
	}

}
class YieldThread extends Thread
{
	public YieldThread(String name)
	{
		super(name);
	}
	public void run()
	{
		for(int i=0;i<5;i++)
		{
			System.out.println(Thread.currentThread().getName()+"----"+i);
			if(i==3)
			{
				System.out.print("线程让步:");
				Thread.yield();//线程运行到此,做出让步
			}
		}
	}
}


六、线程插队

package com.test.xiancheng;

public class XCchadui {
	public static void main(String[] args) throws Exception {
		Thread t = new Thread(new EmergencyThread(),"线程一");
		t.start();
		for(int i=1;i<6;i++)
		{
			System.out.println(Thread.currentThread().getName()+"输入:"+i);
			if(i==2)
			{
				t.join();
			}
			Thread.sleep(500);
		}
	}

}
class EmergencyThread implements Runnable
{
	public void run()
	{
		for(int i=1;i<6;i++)
		{
			System.out.println(Thread.currentThread().getName()+"输入:"+i);
			try
			{
				Thread.sleep(500);
			}
			catch(InterruptedException e)
			{
				e.printStackTrace();
			}
		}
	}
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值