1 线程的基础知识(上)

<线程的创建与启动</span></h1><p></p><p>总结下有三种方式:<常用的就是前面两种第一种 创建Thread类的子类对象</span></h2><p>1定义Thread类的子类</p><p>2重写run()方法</p><p>3创建Thread的子类实例,创建线程对象</p><p>4调用start()的start()方法来启动该线程</p><pre name="code" class="java">public class ThreadOne extends Thread //第一步 定义一个类继承Thread
{
	private  int a;//定义一个成员变量
	//重写run()方法
	public  void run(){
		for(;a<249;a++)
		{
			System.out.println(getName()+""+a);
		}
		
	}

	public static void main(String[] args) {
		// TODO Auto-generated method stub
      for(int a=0;a<249;a++)
      {
    	  System.out.println(Thread.currentThread().getName()+"--"+a);
    	  if( a==10)
          {
        	 //创建线程
    		   ThreadOne TO=new ThreadOne();
    		   //启动该线程
    		   TO.start();
    		  
    		   ThreadOne TW=new ThreadOne();
    		   TW.start();
    		   

    		   ThreadOne TH=new ThreadOne();
    		   TH.start();
        	  
    		   //还是可以采用链式编程
    		   new ThreadOne().start();
    		   
    		   new ThreadOne().start();
    		   
    		   
    	}
      }
    
	}
}

第二种  实现Runnable接口创建线程类

1定义Runnable接口地实现类

2重写该接口的run()的方法

3创建该Runnable()接口实现类的实例

4启动start()方法

注意:API中

Thread(Runnable target)
          分配新的 Thread 对象。
Thread(Runnable target,String name) 

有这两个方法

//定义一个类实现Runnable接口
public class RunnableTwo implements Runnable {
	
	private int a;
	//重写run()方法
	public void run(){
		for(;a<249;a++)
		{
			//注意,这里跟第一个程序不同?实现Runnable接口的类必须要注意实现currentThread()方法
			System.out.println(Thread.currentThread().getName()+"--"+a);
		}
		
	}

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		for(int a=0;a<259;a++)
		{
			System.out.print(Thread.currentThread().getName()+"—-"+a);
			if(a==10)
			{
				//Runnable类实现实例化
				RunnableTwo RT=new RunnableTwo();
				//通过构造器实现线程
				Thread one=new Thread(RT,"1");
				Thread two=new Thread(RT,"2");
				
				//启动线程
			    one.start();
			    two.start();
				
			}

		}
		
	}

}

我们一般喜欢采用第二个方法;

当然查阅API在Java5中还新增了一种方法;接下来来讲下该方法

第三种Callable

看API是怎么介绍的

java.util.concurrent
接口 Callable<V>

类型参数:
V - call 方法的结果类型
所有已知子接口:
JavaCompiler.CompilationTask

public interface Callable<V>
 
 

返回结果并且可能抛出异常的任务。实现者定义了一个不带任何参数的叫做 call 的方法。

Callable 接口类似于 Runnable,两者都是为那些其实例可能被另一个线程执行的类设计的。但是Runnable 不会返回结果,并且无法抛出经过检查的异常。

Executors 类包含一些从其他普通形式转换成Callable 类的实用方法。

从以下版本开始:
1.5
另请参见:
Executor

方法摘要
 Vcall()           计算结果,如果无法计算结果,则抛出一个异常。

第一我们可以读出有返回值

第二读不出来的就就抛出异常

但是这里就很难受了,知道了这些并不能调用,返回值作为targer太扯淡了,我继续查了下API

接口 Future<V>

类型参数:
V - 此 Future 的 get 方法所返回的结果类型
booleancancel(boolean mayInterruptIfRunning)           试图取消对此任务的执行。
 Vget()           如有必要,等待计算完成,然后获取其结果。
 Vget(long timeout,TimeUnit unit)           如有必要,最多等待为使计算完成所给定的时间之后,获取其结果(如果结果可用)。
 booleanisCancelled()           如果在任务正常完成前将其取消,则返回true
 booleanisDone()           如果任务已完成,则返回true。

这又是一个接口,再看看有没有现成的类

类 FutureTask<V>

FutureTask(Callable<V> callable)           创建一个FutureTask,一旦运行就执行给定的 Callable
FutureTask(Runnable runnable,V result)           创建一个FutureTask,一旦运行就执行给定的 Runnable,并安排成功完成时 get 返回给定的结果 。

哈哈,终于找到我们想要的东西,不BB,直接上代码。

import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;

public class ThreeCallable implements Callable<Integer> {
      private int a;
      private int b;
      //重写call()方法
      public Integer call() throws Exception{
    	  for(int a=0;a<249;a++)
    	  {
    		  System.out.println(Thread.currentThread().getName()+"--"+a);
    	       while(a==100){
    	    	   b=a;
    		      break;
    	       }
    	  }
    	  return b;
      }
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		//创建该对象实例化
		ThreeCallable TC=new ThreeCallable();
		//FutureTask是一个类,类里传入TC这个实例,来得到放回值类型
		FutureTask<Integer> target=new FutureTask<Integer>(TC);
		
	    for(int a=0;a<249;a++)
	    {
	    	System.out.println(Thread.currentThread().getName()+"--"+a);
	    	if(a==10)
	    	{
	    		
	    	new Thread(target,"1").start();
	    
	    	
	    	}
	    }
	    try
	    {
	   // 得到放回值
	    	System.out.println("线程返回值"+target.get());
	    }
	    catch(Exception ex)
	    {
	    	ex.printStackTrace();
	    }

	}

}


现在来总结下:

想要取得Callable返回值的方法,不想要返回值的话就跟第二种一样了

1 定义一个类实现Callable接口;

2 重写run方法

3创建这个类的实例

4使用FutureTask类来包装Thread类的对象。

5上步骤中的对象来作为Thread的target对象创建,接着启动线程

6通过get()方法来得到返回值类型。



总结:三种方式的优缺点

1后面2种方式明显可以体现出多态,不仅能实现Runnable、Callable接口,还可以实现其他接口

2后面两种多个线程可以共享一个target。

3前面编写比较简单,后面两种方式就比较多。


线程的周期


新建到就绪:通过start()方法调用后即可。


就绪到运行:需要配置CPU资源。


运行到阻塞:1 sleep()方法。

                         2 IO阻塞

                         3 等待同步锁

                         4 suspend()把程序挂起,这可能会导致死锁。

                        5 等待通知wait()。


阻塞到就绪:1 sleep()时间到了

                        2 IO方法放回

                        3 获得同步锁

                        4 等待收到通知notify()。唤醒线程。nofityAll(),唤醒所有线程。

                         5 resume()重写开始 


运行到阻塞: 1 yield()线程让步

                         2 失去CPU资源


就绪到死亡: 1 stop()停止

                         2  Error()或者Exception

                         3  run()/call()方法执行完成



控制线程

等待线程join()方法
voidjoin()
          等待该线程终止。
 voidjoin(long millis)
          等待该线程终止的时间最长为 millis 毫秒。
 voidjoin(long millis, int nanos)
          等待该线程终止的时间最长为 millis 毫秒 + nanos 纳秒。

后台线程setDaemon()
voidsetDaemon(boolean on)
          将该线程标记为守护线程或用户线程。

线程睡眠sleep()
static voidsleep(long millis)
          在指定的毫秒数内让当前正在执行的线程休眠(暂停执行),此操作受到系统计时器和调度程序精度和准确性的影响。
static voidsleep(long millis, int nanos)
          在指定的毫秒数加指定的纳秒数内让当前正在执行的线程休眠(暂停执行),此操作受到系统计时器和调度程序精度和准确性的影响。

线程让步yield()
static voidyield()
          暂停当前正在执行的线程对象,并执行其他线程。

改变线程优秀级
voidsetPriority(int newPriority)
          更改线程的优先级。
一般默认是5,最大是10,最小是1。


如果你觉得可以请点赞奋斗

转载于:https://www.cnblogs.com/linjingjia/p/7198289.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值