首页 > 编程语言 > 详细

java多线程

时间:2020-03-23 01:07:10      阅读:90      评论:0      收藏:0      [点我收藏+]

多线程的实现

并发:指两个或多个事件在同一时间段内发生
并行:指两个或多个事件在同一时刻发生/同时发生

进程:指有关内存中运行的应用程序
线程:进程中的一个执行单元,一个程序运行后至少有一个进程,一个进程可以包含多个线程

线程存在优先级

创建多线程的第一种方法

实现步骤:
1、创建一个Thread类的子类
2、在Thread类的子类中重写Thread类中的run方法,设置线程任务
3、创建Thread类的子类对象
4、调用Thread类中的start方法,java虚拟机调用该线程的run方法

java程序属于抢占式调度,哪个线程的优先级高,就先调用哪个线程。

public class Thread1 extends Thread {
    @Override
    public void run(){
        for (int i = 0; i < 20; i++) {
            System.out.println("子线程");
        }
    }
}
public class Test1 {
    public static void main(String[] args) {
        Thread1 thread1 = new Thread1();
        thread1.start();
        for (int i = 0; i < 20 ; i++) {
            System.out.println("主线程");
        }
    }
}

Thread类的常用方法

1、获取线程的名称
使用Thread类中的getName()
可以先获取到当先正在执行的线程,使用线程中的方法getName()获取线程的名称

public class Thread2 extends Thread {
    @Override
    public void run(){
        String name = getName();
        System.out.println(name);
//        Thread thread = Thread2.currentThread();
//        System.out.println(thread);
//        String name1 = thread.getName();
//        System.out.println(name1);
        System.out.println(Thread2.currentThread().getName());
    }
}
public class Test2 {
    public static void main(String[] args) {
        Thread2 thread2 = new Thread2();
        thread2.start();

        new Thread2().start();
        new Thread2().start();

        System.out.println(Thread2.currentThread().getName());

    }
}

2、设置线程的名称
使用Thread类中的setName(name)
创建一个带参数的构造方法,参数传递线程的名称,调用父类的带参构造方法,把线程名称传递给父类,让父类给子线程起一个名字。

3、暂停执行
Thread类中的sleep方法,使当前正在执行的线程以指定的毫秒数暂停,毫秒数结束后,线程继续执行,这个方法是一个静态方法,Thread.sleep(1000);


创建线程的第二种方式(常用)

实现Runnable接口
Thread类的构造方法可以传递Runnabel对象

实现步骤:
1、创建一个Runnable接口的实现类
2、在实现类中重写Runnable接口的run方法,设置线程任务
3、创建一个Runnable接口的实现对象
4、创建Thread类对象,构造方法传递Runnable接口的实现对象
5、调用Thread类创建对象的start方法

public class RunnableIpm implements Runnable {
    @Override
    public void run() {
        for (int i = 0; i < 20 ; i++) {
            System.out.println(i);
        }
    }
}
public class Test3 {
    public static void main(String[] args) {
        RunnableIpm runnableIpm = new RunnableIpm();
        Thread thread = new Thread(runnableIpm);
        thread.start();
        for (int i = 0; i < 20 ; i++) {
            System.out.println(i);
        }
    }
}

实现Runnable接口创建多线程的好处

1、避免单继承的局限性
一个类只能继承一个类
2、增强了程序的扩展性,解耦
实现Runnable接口的方式,把设置线程任务和开启新线程进行了分离

匿名内部类方式实现线程的创建

匿名:没有名字
内部类:写在其他类的内部

匿名内部类:把子类继承父类,重写父类的方法,创建子类对象合成一步完成
把实现类实现类接口,重写接口中的方法,创建实现类对象合成一步完成
最终子类/实现对象 没有名字
格式:
new 父类/接口(){
重写父类/接口中的方法
}

public class Test4 {
    public static void main(String[] args) {
        new Thread(){
            @Override
            public void run(){
                for (int i = 0; i < 20; i++) {
                    System.out.println(Thread.currentThread().getName());
                }
            }
        }.start();

        System.out.println("-------------------");

        Runnable runnable =  new Runnable(){
            @Override
            public void run(){
                for (int i = 0; i < 20; i++) {
                    System.out.println(Thread.currentThread().getName());
                }
            }
        };
        new Thread(runnable).start();

        System.out.println("---------------------");

        new Thread(new Runnable(){
            @Override
            public void run(){
                for (int i = 0; i < 20; i++) {
                    System.out.println(Thread.currentThread().getName());
                }
            }
        }).start();
    }
}

线程的状态

等待唤醒机制

Wating

线程间的通讯wait()和notify():
    创建一个线程,调用wait方法,放弃CPU的执行,进入到waiting状态(无限等待)
    创建一个线程,调用notify方法,唤醒上面的线程

注意:
    两个线程必须使用同步代码块包裹起来,保证等待和唤醒只有一个任务执行
    同步使用的锁对象必须保证唯一
    只有锁对象才能调用wait和notify方法
    void wait()在其他线程调用此对象的notify方法或notifyAll()方法前,当前线程处于等待状态
    
   void notify()唤醒在此对象监视器上等待的单个线程,会继续执行wait方法之后的代码
   
   wait()和notify()方法必须要在同步代码块或者同步方法中使用,必须通过锁对象来调用这两个方法
public class WaitNotify {
    public static void main(String[] args) {
        Object object = new Object();

        new Thread(){
            @Override
            public void run() {
                // 保证等待和唤醒的线程只能有一个执行,需要同步
                synchronized (object){
                    System.out.println("等待");
                    try {
                        object.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    //唤醒之后执行的代码
                    System.out.println("唤醒后的代码");
                }
            }
        }.start();

        new Thread(){
            @Override
            public void run() {
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (object){
                    System.out.println("唤醒");
                    object.notify();
                }
            }
        }.start();
    }
}

线程池

原理

当程序第一次启动的时候,创建多个线程,保存到一个集合中,当我们想要使用线程的时候,就可以从集合中取出线程来使用。
Thread t = list.remove(0):返回的是被移除的元素(线程只能被一个任务使用)

当我们使用完毕线程,需要把线程归还给线程池
list.add(t)

线程的使用

类Executors

Executors类中的静态方法
static ExecutorService newFixedThreadPool(int nThreads)
创建一个可重用固定线程数的线程池

参数 int nThreads:创建线程池中包含的线程数量

返回值:ExecutorService接口,返回的是ExecutorService接口的实现类对象,我们可以使用ExeutorService接口接收

ExeutorService接口中的方法submit(Runnable task)提交一个Runnable任务执行
shutdown()关闭线程

使用步骤:
1、使用线程池的工厂类Executor里边提供的静态方法生产一个指定线程数量的线程池
2、创建一个类,实现Runnable接口,重写run方法,设置线程任务
3、调用ExecutorService中的submit,传递线程任务(实现类),开启线程,执行run方法

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ThreadPool {
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newFixedThreadPool(3);
        executorService.submit(new RunnableImpl2());
        executorService.submit(new RunnableImpl2());
        executorService.submit(new RunnableImpl2());
        executorService.submit(new RunnableImpl2());
        executorService.submit(new RunnableImpl2());
        executorService.submit(new RunnableImpl2());
        executorService.shutdown();
    }
}
public class RunnableImpl2 implements Runnable {
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + "正在执行");
    }
}

java多线程

原文:https://www.cnblogs.com/saonian450/p/12549552.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!