JAVA多线程

多线程概述

多线程是指从软件或者硬件上实现多个线程并发执行的技术。具备多线程能力的计算机因有硬件支持而可以在同一时间执行多于一个线程,进而提高总体处理性能。java

多线程实现

1.继承Thread

自定义类继承Thread类,重写其中的run()方法(即写入想让该线程执行的代码),在main()函数中建立该类,并调用start()方法就会启动多线程并执行run()中的代码多线程

class MyThread extends Thread{
    private String greeting;
    MyThread(String s){
        greeting=s;
    }

    @Override
    public void run() {
        while (true)
        System.out.println(greeting);
    }
}
public class ThreadTest {
    public static void main(String[] args){
        MyThread ms1=new MyThread("haha");
        MyThread ms2=new MyThread("ahah");
        ms1.start();
        ms2.start();
    }
}

2.实现Runnable接口

自定义类实现Runnable接口而且重写run()方法(即写入想让该线程执行的代码)并发

建立自定义类对象,再以该对象为参数建立Thread对象,最后使用Thread对象调用start()方法,即多线程完成启动ide

class MyThread implements Runnable{
    private String greeting;
    MyThread(String s){
        greeting=s;
    }

    @Override
    public void run() {
        while(true)
        System.out.println(greeting);
    }
}
public class ThreadTest {
    public static void main(String[] args){
        MyThread ms1=new MyThread("haha");
        MyThread ms2=new MyThread("ahah");
        new Thread(ms1).start();
        new Thread(ms2).start();
    }
}

两种方式对比

  1. 继承Thread
    • 好处:能够直接使用Thread类中的方法,代码简单
    • 弊端:若是已经有了父类,就不能用这种方法
  2. 实现Runnable接口
    • 好处:即便本身定义的线程类有了父类也能够,由于有了父类也能够实现接口,并且接口是能够多实现的
    • 弊端:不能直接使用Thread中的方法须要先获取到线程对象后,才能获得Thread的方法,代码复杂

匿名内部类写法

  1. 继承Thread类
public class ThreadTest {
    public static void main(String[] args){
        new Thread(){
            @Override
            public void run() {
                while (true)
                    System.out.println("haha");
            }
        }.start();
    }
}
  1. 实现Runnable接口
public class ThreadTest {
    public static void main(String[] args){
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (true)
                    System.out.println("haha");
            }
        }).start();
    }
}

Thread方法

设置和获取线程名

//构造Thread时设置线程名
Thread(Runnable target, String name) 
//分配一个新的 Thread对象。  
Thread(String name) 
//分配一个新的 Thread对象。  
    
void setName(String name) 
//将此线程的名称更改成等于参数 name 。     
    
String getName() 
//返回此线程的名称。

获取当前线程的对象

static Thread currentThread() 
//返回对当前正在执行的线程对象的引用。

休眠,等待与唤醒线程

static void sleep(long millis) 
//使当前正在执行的线程以指定的毫秒数暂停(暂时中止执行),具体取决于系统定时器和调度程序的精度和准确性。
void wait() 
//致使当前线程等待,直到另外一个线程调用该对象的 notify()方法或 notifyAll()方法。 
void notify() 
//唤醒正在等待对象监视器的单个线程。  
void notifyAll() 
//唤醒正在等待对象监视器的全部线程。

标记守护线程

守护线程又称后台线程,服务线程.普通线程在执行结束后中止,而守护线程服务于普通线程,当普通线程都中止守护进程也当即中止(服务对象消失)函数

void setDaemon(boolean on) 
//将此线程标记为 daemon线程或用户线程。
class MyThread extends Thread{
    private long last;
    MyThread(long last){//休眠时间
        this.last=last;
    }

    @Override
    public void run() {//休眠last秒而后打印该线程名
        try {
            sleep(last);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(this.getName());
    }
}
public class ThreadTest {
    public static void main(String[] args) throws InterruptedException {
        MyThread ms1=new MyThread(1000);//守护线程持续时间短
        ms1.setName("Daemon thread");
        MyThread ms2=new MyThread(4000);
        ms2.setName("Normal thread");
        ms1.setDaemon(true);
        ms1.start();
        ms2.start();
    }
}
//输出结果
//Daemon thread
//Normal thread
//若是将main中的代码改成如下
MyThread ms1=new MyThread(4000);//守护线程持续时间长
ms1.setName("Daemon thread");
MyThread ms2=new MyThread(1000);
ms2.setName("Normal thread");
ms1.setDaemon(true);
ms1.start();
ms2.start();
//输出结果
//Normal thread
//因为普通线程早于守护线程中止,守护线程也被迫中止(没来得及运行)

加入线程

void join() 
//等待这个线程死亡。  
void join(long millis) 
//等待这个线程死亡最多 millis毫秒。
class MyThread extends Thread{
    private long last;
    MyThread(long last){//休眠时间
        this.last=last;
    }

    @Override
    public void run() {//休眠last秒而后打印该线程名
        try {
            sleep(last);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(this.getName());
    }
}
public class ThreadTest {
    public static void main(String[] args) throws InterruptedException {
        MyThread ms1=new MyThread(1000);//守护线程持续时间短
        ms1.setName("first");
        MyThread ms2=new MyThread(4000);
        ms2.setName("second");
        ms2.start();
        ms2.join();//加入线程
        ms1.start();
    }
}
//线程1的睡眠时间短本应线程1先输出,但因为线程1执行前调用了线程1的join(),
//该函数会等待线程1中止才继续下面的代码
//因此输出
//second
//first

代码同步

当须要一段事务代码须要连续执行而不容许由于多线程的CPU调度在执行过程当中切换线程,这样就须要代码同步达到这个要求性能

同步后的代码不会在执行过程当中发生中断,也就是说CPU必须一口气执行完毕this

同步代码块

  • 同步代码块即便用synchronized关键字加上一个锁对象来定义一段代码线程

  • 多个同步代码块若是使用相同的锁对象, 那么他们就是同步的code

    public class ThreadTest {
        public static void main(String[] args){
            Object o=new Object();
            new Thread(){
                @Override
                public void run() {
                    while (true) {
                        synchronized (o) {//锁对象能够是任意对象,可是被锁的代码须要保证是同一把锁,不能用匿名对象
                            for (int i = 0; i < 10; i++) {
                                System.out.print(i);
                            }
                            System.out.println();
                        }
                    }
                }
            }.start();
            new Thread(){
                @Override
                public void run() {
                    while (true) {
                        synchronized (o) {
                            for (int i = 0; i < 10; i++) {
                                System.out.print(i);
                            }
                            System.out.println();
                        }
                    }
                }
            }.start();
        }
    }
    //若是不加synchronized那么打印出来的的不必定每一行都是0123456789

同步方法

  • 静态方法同步锁对象是当前类的字节码对象
  • 非静态同步方法锁对象是this
public static synchronized void printNum() {    
    //使用synchronized关键字修饰的方法中全部的代码都是同步的
    for(int i=0;i<10;i++)
        System.out.println();
}

Timer(计时器)

  • 对任务进行定时规划运行
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;

public class ThreadTest {
    public static void main(String[] args) throws InterruptedException {
        Timer t = new Timer();
        t.schedule(new MyTimerTask(), new Date(),3000);//三秒打印一次O(∩_∩)O
        while(true) {
            System.out.println(new Date());//每秒打印一次时间
            Thread.sleep(1000);
        }
    }
}
class MyTimerTask extends TimerTask {
    @Override
    public void run() {
        System.out.println("O(∩_∩)O");
    }
}
相关文章
相关标签/搜索