Java多线程

2022/3/31 20:19:45

本文主要是介绍Java多线程,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

Java多线程

多线程优点:提高程序响应,增强用户体验;提高利用率;改善程序结构;

线程创建一:继承java.lang.Thread类

class MyThread extends Thread{//1、创建类继承于Thread
    @Override
    public void run(){  // 2、重写run()方法 执行任务
        for (int i = 0; i < 100; i++) {
            if(i%2==0) System.out.println(i);
        }
    }
}

public class ThreadTest {
    public static void main(String[] args) {
        MyThread t1 = new MyThread();   //3、创建子类对象
        t1.start();//4、调用对象的start()方法
        for (int i = 0; i < 100; i++) {
            if(i%2!=0) System.out.println(i+"****");
        }
    }
}
/*
	不能直接调用run()方法,那样还是主线程在执行
	已经start()过的线程不能执行,IllegalThreadStateException,需要重新创建线程对象
*/
/*
	匿名子类
*/
public class ThreadTest {
    public static void main(String[] args) {
        new Thread(){
            @Override
            public void run(){
                //。。。
            }
        }.start();
    }
}

线程创建二:实现Runnable接口

class MyThread implements Runnable{//1、创建一个类实现Runnable接口的类
    @Override
    public void run(){//2、实现抽象方法run()
        for (int i = 0; i < 100; i++) {
            if(i%2==0) System.out.println(i);
        }
    }
}
public class ThreadTest {
    public static void main(String[] args) {
        MyThread myThread = new MyThread();//2、创建类的对象
        Thread t1 = new Thread(myThread);//3、将此对象作为参数传递到Thread类的构造器中门窗及Thread类的对象
        t1.start(); //5、通过Thread类的对象调用start();
        for (int i = 0; i < 100; i++) {
            if(i%2!=0) System.out.println(i+"****");
        }
    }
}

线程创建三:实现Callable接口

class NumThread implements Callable {//1、创建一个实现Callable的实现类
    @Override
    public Object call() throws Exception {//2、实现Call()方法
        int sum = 0;
        for (int i = 1; i <= 100; i++) {
            if(i % 2 == 0){
                System.out.println(i);
                sum += i;
            }
        }
        return sum;
    }
}
public class ThreadTest {
    public static void main(String[] args) {
        NumThread numThread = new NumThread();//3、创建Callable实现类的对象
        FutureTask futureTask = new FutureTask(numThread);//4、将此对象作为参数传递到FutureTask构造器,创建FutureTask的对象
        new Thread(futureTask).start();//5、将创建FutureTask的对象作为参数传递到Thread构造器,创建Thread对象并调用start(),FutureTask实现了Runnable方法
        try{
            // 6、可以获取call返回值
            //get()返回值为FutureTask构造器参数Callable实现类重写的call()的返回值
            Object sum = futureTask.get();
            System.out.println("和为:"+sum);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }
}

线程创建四:线程池

class NumberThread implements Runnable{
    @Override
    public void run() {
        for(int i=0;i<=100;i++){
            if(i%2==0){
                System.out.println(i);
            }
        }
    }
}

public class ThreadPool {

    public static void main(String[] args) {
        // 1、提供指定线程数量的线程池
        ExecutorService service = Executors.newFixedThreadPool(10);
        
        //设置线程池属性
        ThreadPoolExcutor service1 = (ThreadPoolExcutor)service;
        service1.setCorePoolSize(15);
        ...
	    // 2、执行指定的线程操作
        service.execute(new NumberThread());//适合使用Runnable
//        service.submit();//适合使用Callable
        // 3、关闭连接池
        service.shutdown();
    }
}

方式一、二比较

开发中优先选择实现Runnable接口

  • 实现方式没有单继承的局限性

  • 更适合处理多个线程有共享数据的情况

public class Thread implements Runnable

线程调用

时间片、抢占式

  • Java调度方法

    同优先级线程组成先进先出队列,时间片策略

    高优先级,优先调度抢占式策略

  • 线程优先级

    /*
    	MAX_PRIORITY:10
        MIN_PRIORITY:1
        NORM_PRIORITY:5
    */
    getPriority();
    setPriority(int p);
    

Thread类常用方法

start();
run();
currentThread();//静态方法,返回当前代码的线程
getName();
setName();
yield();//让一步
join();//插队  
stop(); //Deprecated 强制结束
sleep(long millitime);
isAlive();

程序、进程、线程理解:

程序:静态代码,某种语言编写的一组指令的集合,为了完成特定任务。

进程:正在运行的程序

线程:是一个程序内部的一条执行路径

并发与并⾏

并发: 同⼀时间段,多个任务都在执⾏ (单位时间内不⼀定同时执⾏);

并⾏: 单位时间内,多个任务同时执⾏。

线程生命周期

线程安全

  • 同步代码块

    symchronized(同步监视器){
    	...
    }
    
  • 同步方法

    public synchronized void run(){
        ...
    }
    

线程安全懒汉式

class Bank(){
	private Bank();
    private static Bank instance = null;
    public static Bank getInstance(){
        //方式一、效率低
        synchronized (Bank.class) {
			if(instance == null) instance = new Bank();
             return instance;
        }
        //方式二、效率更高
        if(instance==null){
            synchronized (Bank.class) {
                if(instance == null){
                    instance = new Bank();
                }
            }
        }
        return instance
    }
}

死锁问题

  1. 互斥条件:该资源任意⼀个时刻只由⼀个线程占⽤。
  2. 请求与保持条件:⼀个进程因请求资源⽽阻塞时,对已获得的资源保持不放。
  3. 不剥夺条件:线程已获得的资源在末使⽤完之前不能被其他线程强⾏剥夺,只有⾃⼰使⽤完毕 后才释放资源。
  4. 循环等待条件:若⼲进程之间形成⼀种头尾相接的循环等待资源关系。

Lock锁

private ReentrantLock lock = new ReentrantLock();

@Override
public void run(){
	...
        try{
        	lock.lock();
            ...
        }finally{
			lock.unlock();
        }
}

相比synchronized性能好,需要手动开启关闭。

线程通信

wait();
notify();
notifyAll();

sleep()和wait()异同

  • 两者最主要的区别在于: sleep() ⽅法没有释放锁,⽽ wait() ⽅法释放了锁 。
  • 两者都可以暂停线程的执⾏。
  • wait() 通常被⽤于线程间交互/通信, sleep() 通常被⽤于暂停执⾏。
  • wait() ⽅法被调⽤后,线程不会⾃动苏醒,需要别的线程调⽤同⼀个对象上的 notify() 或 者 notifyAll() ⽅法。 sleep() ⽅法执⾏完成后,线程会⾃动苏醒。或者可以使⽤ wait(long timeout) 超时后线程会⾃动苏醒


这篇关于Java多线程的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程