JavaSE--线程1

本文详细介绍了Java中线程的概念、串行与并发的区别,并展示了通过继承Thread、实现Runnable和Callable接口创建线程的方法。还提供了线程生命周期、常用方法的概述,以及多个线程实战示例,包括并发打印奇偶数、读取目录下文件内容、模拟电视观看与快递接收、多线程龟兔赛跑等,强调了多线程在提高程序效率中的作用。
摘要由CSDN通过智能技术生成


一、线程的概念

  1.程序和进程

    程序:程序是一种静态概念,磁盘上的一系列文件组成一个程序

    进程:进程是一种动态概念,是运行中的程序,一个程序有一个或多个进程

   2.进程和线程的区别

    进程是程序执行是相关资源分配的最小单位,进程之间是相互独立互不干扰的,一个进程包含一个或多个线程

    线程是CPU分配的最小单位,线程之间共享进程的内存,线程有自己独立的空间

二、串行,并行,并发

串行:多个指令一个一个的执行
并发:每个线程单独运行,CPU在这些线程中切换执行,线程并不是一起执行的
并行:多个CPU内核执行多个线程,实现多个线程同时执行

三、线程的实现

线程的实现有四种方式:
1.继承Thread类
2.实现Runnable接口
3.实现Callable接口
4.使用线程池
1. 继承Thread
1.继承Thread类,重写run方法,调用starts方法
class MyThread extends Thread{

    @Override
    public void run() {
        for (int i = 0; i < 1000; i++) {
            System.out.println(Thread.currentThread().getName()+"启动"+i+"次");
        }
    }
}

public class ThreadTest {
    public static void main(String[] args) throws InterruptedException {
        MyThread myThread1=new MyThread();
        myThread1.start();
        for (int i = 0; i < 1000; i++) {
            System.out.println(Thread.currentThread().getName()+"启动"+i+"次");
        }

    }
}
2.实现Runnable接口
1.实现Runnable接口,实现run方法,创建实现Runnable接口的对象,创建Thread对象传入实现Runnable接口的对象
调用start方法

class MyRunnable implements Runnable{
    @Override
    public void run() {
        for (int i = 0; i < 1000; i++) {
            System.out.println(Thread.currentThread().getName()+"--"+i);
        }
    }
}

public class RunnableTest {
    public static void main(String[] args) {
        //实现Runnable接口,方法一
        MyRunnable myRunnable=new MyRunnable();
        //实现Runnable接口,方法二,匿名内部类
        Thread thread=new Thread(myRunnable);
        Thread thread1=new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 1000; i++) {
                    System.out.println(Thread.currentThread().getName()+"--"+i);
                }
            }
        });
        //实现Runnable接口,方法三,lamda表达式
        Thread thread2=new Thread(()->{
            for (int i = 0; i < 1000; i++) {
                System.out.println(Thread.currentThread().getName()+"--"+i);
            }
        });
        thread.start();
        thread1.start();
        thread2.start();
        for (int i = 0; i < 1000; i++) {
            System.out.println(Thread.currentThread().getName()+"--"+i);
        }
    }
}
3.实现Callable接口

1.实现Callable接口,实现call方法,创建实现Callable接口的对象,创建FutrueTask对象传入实现Callable接口的对象,创建Thread对象传入FutrueTask对象,调用start方法

class MyCallable implements Callable<Long>{

    @Override
    public Long call() throws Exception {
        long sum=0;
        for (int i = 0; i < 1000000; i++) {
            sum+=i;
        }
        return sum;
    }
}

public class CallableTest {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        FutureTask futureTask=new FutureTask(new MyCallable());
        Thread thread=new Thread(futureTask);
        thread.start();
        System.out.println("执行结果");
        System.out.println(futureTask.get());
    }
}

Thread,Runnable,Callable创建线程的区别

1.Thread创建线程是继承,因为java是单继承,会导致继承Thread的类不能继承别的类
2.Runnable和Callable是实现接口,java可以多实现
3.在实现Runnable,和Callable接口时,必须实现run方法和Call方法,不容易出错
4.Callable有返回值,可以通过get()方法获取返回值,Runnable和Thread是没有返回值的

三、线程的生命周期

在这里插入图片描述

五.线程常用方法

方法使用
start()启动线程
stop停止线程,紧张使用,可能会导致线程死锁等问题
getName获得线程名称
setName设置线程名称
sleep线程休眠
setPriorty设置线程的优先级(1-10)等级越高,抢占CPU的几率更大
setDaemon设置为后台线程,TRUE,守护其他线程,为其他线程服务,如 GC(垃圾回收)如果没有其他线程,后台线程也会关闭
Join线程的加入(合并)插队

练习

package com.tx.work;

/**
 * 1. 设计两个线程,一个线程负责打印1~100以内所有的偶数;然后,另外一个线程负责打印1~100以内所有的奇数。
 *
 * 测试时,分别设置线程的优先级,观察执行的顺序。
 */
public class WorkOne {
    static Thread t1;
    static Thread t2;

    public static void main(String[] args) {
        t1= new Thread(new Runnable() {
            public void run() {
                for (int i=1;i<=100;i++){
                    if (i%2==0){
                        System.out.println("偶数:"+i);
                    }
                }
            }
        });
        t2= new Thread(new Runnable() {
            public void run() {
                for (int i=1;i<=100;i++){
                    if (i%2==1){
                        System.out.println("奇数:"+i);
                    }
                }
            }
        });
        t1.setPriority(Thread.MIN_PRIORITY);
        t2.setPriority(Thread.MAX_PRIORITY);
        t1.start();
        t2.start();
    }
}


/**
 * 实现一个线程,用于扫描某个目录下的所有文本文件(包括:java、txt、html),并将文字内容打印出来。
 */
public class WorkTwo {

    public static void copy(String path){
        File file = new File(path);
        File[] files = file.listFiles();
        for (int i = 0; i < files.length; i++) {
            if (!files[i].isDirectory()) {
                System.out.println();
                try (InputStream inputStream = new FileInputStream(files[i].getAbsolutePath())) {
                    int length = 0;
                    byte[] bs = new byte[1024];
                    while ((length = inputStream.read(bs)) != -1) {
                        String str = new String(bs, 0, length, "utf-8");
                        System.out.println(str);
                    }
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }else {
                copy(files[i].getAbsolutePath());
            }
        }
    }


    public static void main(String[] args) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                copy("D:\\work");
            }
        }).start();
    }
}


/**
 * 某人正在看电视连续剧,从第1~88集,看到第10集时,来了一个送快递的,收完快递后后,继续看电视。
 */
public class WorkThree {
    static Thread thread1;
    static Thread thread;

    public static void main(String[] args) {
         thread=new Thread(()->{
            for (int i = 1; i <= 88; i++) {
                System.out.println("看电视"+i);
                if (i==10){
                    thread1.start();
                    try {
                        thread1.join();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
         thread1=new Thread(()->{
            System.out.println("送快递");
        });
         thread.start();
    }
}


/**
 * 2. 多线程模拟龟兔赛跑:
 *
 * ​	乌龟和兔子进行1000米赛跑,兔子前进5米,乌龟只能前进1米。
 *
 * ​	但兔子每20米要休息500毫秒,而乌龟是每100米休息500毫秒。
 *
 * ​	谁先到终点就结束程序,并显示获胜方
 */
public class WorkFour {
    public static void main(String[] args) {
        Thread rabbit=new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i=0;i<=1000;i+=5){
                    System.out.println("兔子"+i);
                    if (i==1000){
                        System.out.println("兔子胜利");
                        System.exit(0);
                    }
                    if (i%20==0&&i!=0){
                        try {
                            Thread.sleep(500);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        });
        Thread tortoise=new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i <= 1000; i++) {
                    System.out.println("乌龟"+i);
                    if (i==1000){
                        System.out.println("乌龟胜利");
                        System.exit(0);
                    }
                    if (i%100==0&&i!=0){
                        try {
                            Thread.sleep(500);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        });


        rabbit.start();
        tortoise.start();


    }
}

总结

1.为什么用多线程
将一些占用时间长的任务放到后台去运行,来减少程序运行时间,提高程序的运行效率
2.如不执行start直接调用重写或实现的run方法会怎样?
在没有执行start,直接调用run方法,不会创建新的线程,直接在主线程中运行

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值