Java多线程学习笔记

A程序:(简单使用)

 

一、继承Thread类创建线程类 

  1. 重写run方法。该run()方法的方法体就代表了线程需要完成的任务。 
  2. 创建Thread子类的实例。 
  3. 调用线程对象的start()方法来启动该线程
package com.zwh.day01;

class MyThread extends Thread{//定义线程主题
    private String name;
    public MyThread(String name){//给线程设置一个线程名字
        this.name=name;
    }
    @Override   //重写run()方法,必须
    public void run() {//线程运行的主方法
        for (int x=0;x<5;x++){
            System.out.println("【"+this.name+"】线程执行,当前的循环次数为 x="+x);
        }
    }
}
public class Demo {
    public static void main(String[] args) {
        MyThread myThreadA=new MyThread("A线程");
        MyThread myThreadB=new MyThread("B线程");
        MyThread myThreadC=new MyThread("C线程");
        //1、错误启动线程
//        myThreadA.run();
//        myThreadB.run();
//        myThreadC.run();

        //正确启动线程
        myThreadA.start();
        myThreadB.start();
        myThreadC.start();
    }
}

结果:

【A线程】线程执行,当前的循环次数为 x=0
【C线程】线程执行,当前的循环次数为 x=0
【B线程】线程执行,当前的循环次数为 x=0
【C线程】线程执行,当前的循环次数为 x=1
【C线程】线程执行,当前的循环次数为 x=2
【A线程】线程执行,当前的循环次数为 x=1
【C线程】线程执行,当前的循环次数为 x=3
【C线程】线程执行,当前的循环次数为 x=4
【B线程】线程执行,当前的循环次数为 x=1
【B线程】线程执行,当前的循环次数为 x=2
【A线程】线程执行,当前的循环次数为 x=2
【A线程】线程执行,当前的循环次数为 x=3
【A线程】线程执行,当前的循环次数为 x=4
【B线程】线程执行,当前的循环次数为 x=3
【B线程】线程执行,当前的循环次数为 x=4

补充:(自己的源码笔记)

//jdk1.8-----Thread的start()源码,初学者可以跳过
    public synchronized void start() {
        group.add(this);
        boolean started = false;
        try {
            start0();
            started = true;
        } finally {
            try {
                if (!started) {
                    group.threadStartFailed(this);
                }
            } catch (Throwable ignore) {
            }
        }
    }
    private native void start0();//这个方法就是
JNI(Java Native Interface)----本地代码与 Java 虚拟机之间是通过 JNI 函数实现相互操作的

 

二、实现Runnable接口创建线程类 

 

  1. 定义Runnable的实现类,重写run()方法。 

  2. 创建Runnable实现类的实例,并以此作为Thread的target来创建对象,该对象才是真正的线程对象[解释在结果之后]

package com.zwh.day01;

class MyThread implements Runnable{//定义线程主题
    private String name;
    public MyThread(String name){//给线程设置一个线程名字
        this.name=name;
    }
    @Override   //重写run()方法,必须
    public void run() {//线程运行的主方法
        for (int x=0;x<5;x++){
            System.out.println("【"+this.name+"】线程执行,当前的循环次数为 x="+x);
        }
    }
}
public class Demo {
    public static void main(String[] args) {
        MyThread myThreadA=new MyThread("A线程");
        MyThread myThreadB=new MyThread("B线程");
        MyThread myThreadC=new MyThread("C线程");
        new Thread(myThreadA).start();//启动线程并调用run()方法
        new Thread(myThreadB).start();//启动线程并调用run()方法
        new Thread(myThreadC).start();//启动线程并调用run()方法
    }
}

结果:

【B线程】线程执行,当前的循环次数为 x=0
【C线程】线程执行,当前的循环次数为 x=0
【C线程】线程执行,当前的循环次数为 x=1
【C线程】线程执行,当前的循环次数为 x=2
【C线程】线程执行,当前的循环次数为 x=3
【C线程】线程执行,当前的循环次数为 x=4
【A线程】线程执行,当前的循环次数为 x=0
【B线程】线程执行,当前的循环次数为 x=1
【B线程】线程执行,当前的循环次数为 x=2
【B线程】线程执行,当前的循环次数为 x=3
【A线程】线程执行,当前的循环次数为 x=1
【A线程】线程执行,当前的循环次数为 x=2
【B线程】线程执行,当前的循环次数为 x=4
【A线程】线程执行,当前的循环次数为 x=3
【A线程】线程执行,当前的循环次数为 x=4

lamda表达式形式

package com.zwh.day01;

class MyThread implements Runnable{//定义线程主题
    private String name;
    public MyThread(String name){//给线程设置一个线程名字
        this.name=name;
    }
    @Override   //重写run()方法,必须
    public void run() {//线程运行的主方法
        for (int x=0;x<5;x++){
            System.out.println("【"+this.name+"】线程执行,当前的循环次数为 x="+x);
        }
    }
}
public class Demo {
    public static void main(String[] args) {
        for(int x=0;x<3;x++){
            String name=x+"线程对象";
            new Thread(()->{
               for (int i=0;i<5;i++){
                   System.out.println("["+name+"]线程执行,当前循环次数为"+i);
            }
            }).start();//启动线程并调用run()方法
        }
    }
}

结果:

[0线程对象]线程执行,当前循环次数为0
[0线程对象]线程执行,当前循环次数为1
[1线程对象]线程执行,当前循环次数为0
[1线程对象]线程执行,当前循环次数为1
[1线程对象]线程执行,当前循环次数为2
[1线程对象]线程执行,当前循环次数为3
[1线程对象]线程执行,当前循环次数为4
[2线程对象]线程执行,当前循环次数为0
[0线程对象]线程执行,当前循环次数为2
[0线程对象]线程执行,当前循环次数为3
[0线程对象]线程执行,当前循环次数为4
[2线程对象]线程执行,当前循环次数为1
[2线程对象]线程执行,当前循环次数为2
[2线程对象]线程执行,当前循环次数为3
[2线程对象]线程执行,当前循环次数为4

补充:

源码摘取   
  /* What will be run. */
    private Runnable target;//Thread类的成员变量
    public Thread(Runnable target) {//Thread类的构造方法,参数target
        init(null, target, "Thread-" + nextThreadNum(), 0);
    }
    @Override
    public void run() {
        if (target != null) {
            target.run();
        }
    }
Thread调用start()方法来启动一个线程,这时此线程处于就绪(可运行)状态,
并没有运行,一旦得到cpu时间片,就开始执行run()方法,
这里方法 run()称为线程体,它包含了要执行的这个线程的内容,Run方法运行结束,
此线程随即终止。此时的run()就是target的调用

 

三、使用Callable和Future创建线程 

 

  1. 创建Callable接口的实现类,并实现Call()方法,该方法将作为线程执行体,且该方法有返回值,再创建Callable实现类的实例。从Java8开始,可以直接使用Lambda表达式创建Callable对象。 
  2. 使用FutureTask来包装Callable对象,该FutureTask对象封装了该Callable对象的call方法的返回值。 
  3. 使用FutureTask对象作为Thread对象的target创建并启动新线程。 
  4. 调用FutureTask对象的get()方法来获取子线程执行结束后的返回值
package com.zwh.day01;

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

class MyThread implements Callable<String> {//定义线程主题
    @Override
    public String call() {
        String result="";
        for(int i=0;i<5;i++){
            result+="学习多线程,我很开心"+i+"\n";
        }
        return result;
    }
}
public class Demo {
    public static void main(String[] args) throws Exception{

        MyThread myThread = new MyThread();
        FutureTask<String> futureTask=new FutureTask<>(myThread);
        new Thread(futureTask).start();
        System.out.println(futureTask.get());

    }
}

结果:

学习多线程,我很开心0
学习多线程,我很开心1
学习多线程,我很开心2
学习多线程,我很开心3
学习多线程,我很开心4

扩展Callable撸源码,撸出的结构(借用借用,哈哈)

为啥会出现Callable?

//自己撸一撸
public class Thread extends Object implements Runnable
public interface Future<V>    
public interface RunnableFuture<V> extends Runnable, Future<V>
public class FutureTask<V> extends Object implements RunnableFuture<V>{
            FutureTask(Runnable runnable, V result);//补救,Runnable没有返回值
            FutureTask(Callable<V> callable);	//Callable
    		V get();//线程返回结果
        }	
public interface Callable<V>

 

 

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值