Java多线程01

java核心概念

  • 在一个进程中,如果开辟了多个线程,线程的运行由调度器安排调度,调度器是与操作系统紧密相关的,先后顺序是不能人为的干预的。
  • 对同一份资源操作时,会存在资源抢夺的问题,需要加入并发控制
  • 线程会带来额外的开销,如cpu调度时间,并发控制开销
  • 每个线程在自己的工作内存交互,加载和存储主内存控制不当会造成数据不一致。
  • 线程是程序调度和执行的基本单位,而进程是资源分配的单位
  • 线程是进程的一部分,可以称为轻权进程或轻量级进程
  • 很多多线程是模拟出来的,真正的多线程是指有多个cpu,即多核;如果是模拟出来的多线程,即一个cpu的情况下,在同一个时间点,cpu只能执行一个代码,因为切换的很快,所以就有同时执行的错觉。

线程的创建

  1. 继承Thread类

    public class ThreadInit{
        MyThread mt=new MyThread();
        mt.start();
    }
    
    class MyThread extends Thread{
        public void run(){
            //线程方法体
        }
    }
    
    
  2. 实现Runnable接口

    public class ThreadInit{
        MyThread mt=new MyThread();
        Thread t=new Thread(mt);
        t.start();
    }
    
    class MyThread implements Runnable{
        public void run(){
            //线程方法体
        }
    }
    
  3. 实现Callable接口(可返回线程的结果)

    
    
    import java.util.concurrent.Callable;
    import java.util.concurrent.ExecutionException;
    import java.util.concurrent.FutureTask;
    
    public class MyCallable {
    
        public static void main(String[] args) {
    
            /****************方法一******************/
            //创建目标对象
    	    CallStudy cs=new CallStudy("线程");
            //创建执行服务
    	    FutureTask ft=new FutureTask(cs);
            //创建线程对象、关联目标对象、启动线程
    	    new Thread(ft).start();
            //主线程程序
    	    for(int i=97;i<123;i++) {
    		    System.out.println((char)i);
    	    }
            //获取线程结果并输出
    	    try {
    		    result = (String) ft.get();
    		    System.out.println(result);
    	    } catch (InterruptedException | ExecutionException e) {
    		// TODO Auto-generated catch block
    		    e.printStackTrace();
    	    }
    
            /***************方法二*****************/
            //创建目标对象
            CallStudy cs=new CallStudy("线程");
            //创建执行服务
    	    ExecutorService es=Executors.newFixedThreadPool(1);
            //提交执行
    	    Future<String> f=es.submit(cs);
            //主线程程序
    	    for(int i=97;i<123;i++) {
    		    System.out.println((char)i);
    	    }
            //获得线程结果
    	    try {
    		    String str=f.get();
    		    System.out.println(str);
    	    } catch (InterruptedException | ExecutionException e) {
    		    // TODO Auto-generated catch block
    		    e.printStackTrace();
    	    }
            //关闭线程服务
    	    es.shutdownNow();
    
    
        }
    }
    //创建实现Callable的类
    class CallStudy implements Callable{
        private String str;
    
        public CallStudy(String str) {
            super();
            this.str = str;
        }
        //必须实现call方法,可以返回值
        @Override
        public Object call() throws Exception {
    	    // TODO Auto-generated method stub
    	    for(int i=0;i<26;i++) {
    		    System.out.println(i);
    	    }
    	    return "call Thread-->"+this.str;
        }
    
    }
    

**注意:**三种方法中第继承Thread、实现Runnable不能返回结果,而实现Callable能够返回线程结果。

线程状态

线程有五个状态:新生状态、就绪状态、运行状态、阻塞状态、死亡状态。
如下图:
Java多线程01

线程状态详解如下图:
Java多线程01

线程相关方法

  • sleep():使线程停止运行一段时间,此时线程处于阻塞状态。
  • join():插队线程,阻塞其它线程,等待该线程执行完后在执行其它线程。
  • yield(): 礼让线程,当前线程停止,进入就绪状态,此时CPU调度器重新调度线程(不是进入阻塞状态,“礼让”之后不一定是其它线程先执行,也可能是该线程执行)。
  • setDaemon(): 设置守护线程。JVM仅仅确保用户线程执行完,守护线程服务用户线程。
  • setPriority(): 设置线程的优先级。可传参:MIN_PRIORITY、NORM_PRIORITY、MAX_PRIORITY。(优先级低只是意味着获得调度的概率低。并不是绝对先调用优先级高后调用优先级低的线程)。
  • getPriority(): 得到线程的优先级。
  • isAlive():判断线程是否终止。
  • setName(): 给线程命名。
  • getName(): 得到线程的名字。
  • currentThread():获得当前正在运行的线程的对象。

线程的关闭

线程的关闭可以使用stop()方法,但不支持,该方法线程不安全。
可以通过一些变量使线程停止,即线程执行完,如下程序:

package io.github.hu;

public class ThreadStat implements Runnable{
	//判断线程是否停止
    private boolean flag=true;

	private String name;
	
	public void run() {
		int i=0;
		while(flag) {
			System.out.println(name+"--->"+i++);
		}
	}
	
	
	public ThreadStat(String name) {
		super();
		this.name = name;
	}
	
    //使线程停止的方法
	public void over() {
		flag=false;
	}


	public static void main(String[] args) throws InterruptedException {
		ThreadStat ts=new ThreadStat("线程");
		new Thread(ts).start();
		
		for(int i=0;i<99;i++) {
            //当主线程的i=88时,另一个线程停止
			if(i==88) {
				Thread.sleep(5);
				ts.over();
				System.out.println("线程停止");
			}
			System.out.println("main-->"+i);
		}

	}

}