Java多线程

一:了解

1.什么是线程?

①线程(Thread)是一个程序内部的一条执行流程。

②程序中如果只有一条执行流程,那这个程序就是单线程的程序。

2.什么是多线程?

①多线程是指从软硬件上实现的多条执行流程的技术(多条线程由CPU负责调度执行)。

②消息通信、淘宝京东系统都离不开多线程技术。

二:如何在程序中创建出多条线程?

1.Java是通过java.lang.Thread类的对象来代表线程的。

2.多线程的注意事项:

①启动线程必须是调用start方法,不是调用run方法。

②不要把主线程任务放在启动子线程之前。

3.多线程的创建

方式一:继承Thread类

①定义一个子类MyThread继承线程类java.lang.Thread,重写run()方法

②创建MyThread类的对象

③调用线程对象的start()方法启动线程(启动后还是执行run方法的)

方式一的优缺点:

·优点:编码简单

·缺点:线程类已经继承Thread,无法继承其他类,不利于功能的扩展。

public class MyThread extends Thread{
    @Override
    public void run() {
        for (int i = 0; i < 10000; i++) {
            System.out.println("子线程运行"+i);
        }
    }
}
public class ThreadTest1 {
    public static void main(String[] args) {
        MyThread mt = new MyThread();
        mt.start();

        for (int i = 0; i < 10000; i++) {
            System.out.println("主线程运行"+i);
        }
    }
}

方式二:实现Runnable接口

①定义一个线程任务类MyRunable实现Runable接口,重写run()方法

②创建MyRunable任务对象

③把MyRunable任务对象交给Thread处理。

Thread类提供的构造器:

Thread(Runable target) 封装Runable对象成为线程对象

④调用线程对象的start()方法启动线程

方式二的优缺点:

·优点:任务类只是实现接口,可以继续继承其他类、实现其他接口,扩展性强。

·缺点:需要多一个Runable对象。

public class MyRunnable implements Runnable {
    @Override
    public void run() {
        for (int i = 0; i < 10000; i++) {
            System.out.println("子线程运行"+i);
        }
    }
}
public class ThreadTest2 {
    public static void main(String[] args) {
        MyRunnable mr = new MyRunnable();
        Thread t = new Thread(mr);
        t.start();

        for (int i = 0; i < 10000; i++) {
            System.out.println("主线程运行"+i);
        }
    }
}

线程创建方式二的匿名内部类写法

①可以创建Runable的匿名内部类对象

②再交给Thread线程对象

③再调用线程对象的start()启动线程

public class ThreadTest2 {
    public static void main(String[] args) {
        //方式一:
        //        Runnable r = new Runnable() {
        //            @Override
        //            public void run() {
        //                for (int i = 0; i < 10000; i++) {
        //                    System.out.println("子线程运行"+i);
        //                }
        //            }
        //        };
        //        Thread t = new Thread(r);
        //        t.start();
        //方式二:
        //        Thread t = new Thread(new Runnable() {
        //            @Override
        //            public void run() {
        //                for (int i = 0; i < 10000; i++) {
        //                    System.out.println("子线程运行"+i);
        //               }
        //            }
        //        });
        //        t.start();
        //方式三:
        Thread t = new Thread(() -> {
            for (int i = 0; i < 10000; i++) {
                System.out.println("子线程运行"+i);
            }
        }
                             );
        t.start();


        for (int i = 0; i < 10000; i++) {
            System.out.println("主线程运行"+i);
        }
    }
}

方式三:利用Callable接口,FutureTask类来实现。

①创建任务对象

·定义一个类实现Callable接口,重写call方法,封装要做的事情和要返回数据

·把Callable类型的对象封装成FutureTask(线程任务对象)

②把线程任务对象交给Thread对象

③调用Thread对象的start方法启动线程

④线程执行完毕后、通过FutureTask对象的get方法去获取线程任务执行的结果

FutureTask的API

构造器:

FutureTask<>(Callable call) 把Callable对象封装为FutureTask对象

方法:

get() 获取线程执行call方法返回的结果

线程三的优缺点

·优点:线程任务类只是实现接口,可以继续继承类和实现接口,扩展性强;可以在线程执行完毕后去获取线程执行的结果

·确定:编程复杂一点

import java.util.concurrent.Callable;

public class MyCallable implements Callable<String> {
    private int n;

    public MyCallable(int n) {
        this.n = n;
    }

    @Override
    public String call() throws Exception {
        int sum = 0;
        for (int i = 1; i <= n; i++) {
            sum += i;
        }
        return "从1到"+n+"的结果是"+sum;
    }
}
import java.util.concurrent.FutureTask;

public class ThreadTest3 {
    public static void main(String[] args) throws Exception {
        MyCallable mc = new MyCallable(100);
        FutureTask<String> ft = new FutureTask<>(mc);
        new Thread(ft).start();

        //当执行到此处如果上方线程未执行完毕不会获取结果
        //会先暂停等待
        String s = ft.get();
        System.out.println(s);
    }
}

三:Thread的常用方法

1.Thread提供了很多与线程操作相关的方法

构造器:

Thread(String name) 可以为当前线程指定名称

Thread(Runnable target) 封装Runnable对象成为线程对象

Thread(Runable target, String name) 封装Runnable对象成为线程对象,并指定线程名称

方法:

run() 线程的任务方法

start() 启动线程

getName() 获取当前线程的名称,线程名称默认是Thread-索引

setName() 为线程设置名称

public static Thread currentHread() 获取当前执行的线程对象

public static void sleep(long tmie) 让当前执行的线程休眠多少毫秒后,再继续执行

join() 让调用当前这个方法的线程先执行完!可确保线程顺序执行完。

2.示例:

public class MyThread extends Thread{
    public MyThread() {
    }

    public MyThread(String name) {
        super(name);
    }

    @Override
    public void run() {
        Thread t = Thread.currentThread();
        for (int i = 0; i < 5; i++) {
            System.out.println(t.getName()+"运行"+i);
        }
    }
}

public class ThreadTest4 {
    public static void main(String[] args) throws Exception {
        MyThread mt1 = new MyThread();
        mt1.setName("线程一");
        System.out.println(mt1.getName());
        mt1.start();
        mt1.join();

        MyThread mt2 = new MyThread();
        mt2.setName("线程二"); 
        System.out.println(mt2.getName());
        mt2.start();
        mt2.join();

        MyThread mt3 = new MyThread("线程三");
        mt3.start();
        mt3.join();

        Thread t = Thread.currentThread();
        t.setName("主线程");
        System.out.println(t.getName());
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值