Java多线程常用操作方法

2019-07-11  本文已影响0人  Roct

线程的命名和取得

Thread类中的线程名称操作方法

对于线程对象的获取不可能只是依靠一个this来完成的, 因为线程的状态不可控, 但是一定要执行run()方法, 所以可以获取当前线程

eg.
class MyThreadc implements Runnable {
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName());
    }
}
public class RunnableDemo {
    public static void main(String[] args) {
        MyThreadc mt = new MyThreadc();
        new Thread(mt, "线程A").start();
        new Thread(mt).start();
        new Thread(mt, "线程B").start();
    }
}
output
线程A
线程B
Thread-0

当开发者为线程命名的时候就使用设置的名字, 如果没有设置名字, 则会自动生成一个名字, 主要依靠static属性完成的, 在Thread类里定义有如下操作:

private static int threadInitNumber;
private static synchronized int nextThreadNum() {
        return threadInitNumber++;
}
主线程

class MyThreadc implements Runnable {
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName());
    }
}
public class RunnableDemo {
    public static void main(String[] args) {
        MyThreadc mt = new MyThreadc();
        new Thread(mt, "线程A").start();
        mt.run();
    }
}
输出
线程A
main

说明在主函数中执行的是主线程, 在主线程可以创建若干个子线程, 将复杂的逻辑和耗时操作交给子线程.

进程

在执行java命令的时候就表示启动了一个JVM进程, 一台电脑上可以同时启动若干个JVM进程, 每一个JVM的进程都会有各自的线程.

线程的休眠

 new Thread(()->{
            for (int i = 0; i < 6; i++) {
                System.out.println(Thread.currentThread().getName() + ", i = " + i);
                try {
                    Thread.sleep(1000);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }, "线程对象").start();

多个线程执行休眠操作, 休眠顺序有先有后.

线程中断

public boolean isInterrupted();
public void interrupt();

所有正在执行的线程都是可以被终端的, 中断线程的操作必须被异常处理

public static void main(String[] args) throws Exception {
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("线程开启");
                try {
                    Thread.sleep(10000);
                    System.out.println("线程继续");
                } catch (Exception e) {
                    System.out.println("线程卡顿");
                }
                System.out.println("线程继续");
            }
        });
        thread.start();
        Thread.sleep(1000);
        if (!thread.isInterrupted()) {
            System.out.println("线程中断");
            thread.interrupt();
        }
    }

线程强制运行

线程强制运行是指当满足于一些条件以后, 某个线程可以独占资源, 一直到该线程的程序执行结束。

public final void jion() throws InterruptedException

举例

public static void main(String[] args) throws Exception {
        Thread thread = new Thread(new Runnable() {

            Thread mainThread = Thread.currentThread();
            @Override
            public void run() {
            // 不加try..catch...那么主线程和子线程交替执行
                try {
                    mainThread.join(); 
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                try {
                    Thread.sleep(100);
                    } catch (Exception e) {
                }
                for (int i = 0; i < 10; i++) {
                    System.out.println("***一个线程正在执行***" + Thread.currentThread().getName() + ":" + i);
                }
            }
        }, "打酱油");
        thread.start();
        for (int i = 0; i < 10; i++) {
            System.out.println("***一个霸道的线程正在执行***" + Thread.currentThread().getName() + ":" + i);
        }
    }

线程的礼让

线程的礼让是指先将资源让出去给别的线程执行。线程的礼让可以使用Thread的中的

public static void yield()

举例

public static void main(String[] args) throws Exception {
        Thread thread = new Thread(new Runnable() {

            @Override
            public void run() {

                for (int i = 0; i < 100; i++) {
                    if (i % 3 == 0) {
                        Thread.yield();
                        System.out.println("这个线程正在礼让");
                    }
                    try {
                        Thread.sleep(100);
                    } catch (Exception e) {
                    }
                    System.out.println("***一个线程正在执行***" + Thread.currentThread().getName() + ":" + i);
                }
            }
        }, "打酱油");
        thread.start();
        for (int i = 0; i < 100; i++) {
            try {
                Thread.sleep(100);
            } catch (Exception e) {
            }
            System.out.println("***一个霸道的线程正在执行***" + Thread.currentThread().getName() + ":" + i);
        }
    }

礼让执行的时候每次调用yield()方法,每次礼让一次当前的资源。

线程的优先级

从理论上来讲线程的优先级越高越有可能先执行(越有可能先抢占到资源)。在Thread类里面针对于优先级,有两个处理方法
获取优先级:

public final int getPriority()

设置优先级:

public final void setPriority(int newPriority)

在进行优先级定义的时候都是通过int型的数字来完成的,而对于此数字的选择在Thread类中就有明确的定义:
最高优先级

public static final int MAX_PRIORITY    // 10

中等优先级

public static final int NORM_PRIORITY  // 5

最低优先级

public static final int MIN_PRIORITY  // 1

举例

public static void main(String[] args) throws Exception {
        Runnable run = new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 10; i++) {
                    try {
                        Thread.sleep(100);
                    } catch (Exception e) {

                    }
                    System.out.println(Thread.currentThread().getName() + "执行:" + i);
                }
            }
        };
        Thread threadA = new Thread(run, "线程A");
        Thread threadB = new Thread(run, "线程B");
        Thread threadC = new Thread(run, "线程C");
        threadA.setPriority(Thread.MAX_PRIORITY);
        threadB.setPriority(Thread.MIN_PRIORITY);
        threadC.setPriority(Thread.MIN_PRIORITY);
        threadA.start();
        threadB.start();
        threadC.start();
    }

主线程属于中等优先级, 默认的线程的优先级属于中等优先级. 优先级高的有可能先执行, 而不是绝对先执行

线程同步

所谓的线程同步就是指多个操作在同一时间段内只能有一个线程进行, 其他进程等待此线程完成以后才可以继续执行.


线程同步
synchronized(同步对象) {
    同步代码操作
}

public static void main(String[] args) throws Exception {
        Runnable run = new Runnable() {
            private int tiket = 5;
            @Override
            public void run() {
                while (true) {
                    synchronized (this) {
                        if (this.tiket > 0) {
                            try {
                                Thread.sleep(100);
                            } catch (Exception e) {

                            }
                            System.out.println(Thread.currentThread().getName() + "卖票, tiket=" + this.tiket--);
                        } else {
                            System.out.println("卖光啦~");
                            break;
                        }
                    }

                }
            }
        };
        Thread threadA = new Thread(run, "A");
        Thread threadB = new Thread(run, "B");
        Thread threadC = new Thread(run, "C");
        threadA.start();
        threadB.start();
        threadC.start();
    }
public static void main(String[] args) throws Exception {

        Runnable run = new Runnable() {
            private int tiket = 5;

            public synchronized void sale() {
                if (this.tiket > 0) {
                    try {
                        Thread.sleep(1000);
                    } catch (Exception e) {

                    }
                    System.out.println(Thread.currentThread().getName() + "卖票, tiket=" + this.tiket--);
                } else {
                    System.out.println("卖光啦~");
                }
            }
            @Override
            public void run() {
                while (true) {
                    this.sale();
                }
            }
        };
        Thread threadA = new Thread(run, "A");
        Thread threadB = new Thread(run, "B");
        Thread threadC = new Thread(run, "C");
        threadA.start();
        threadB.start();
        threadC.start();
    }

在同步处理以后会造成性能的降低.

线程死锁

优雅的停止线程

多线程的启动是使用的Thread中的start()方法, 而如果对于多线程需要进行停止处理, Thread类提供了stop()方法, 但是从JDK1.2开始就已经被移除

public class Main {
    public static  boolean flag = true;
    public static void main(String[] args) throws Exception {

        Runnable run = new Runnable() {
            @Override
            public void run() {
                long num = 0;
                while (flag) {
                    try {
                        Thread.sleep(50);
                    } catch (Exception e) {}
                    System.out.println(Thread.currentThread().getName() + "正在运行" + num++);
                }
            }
        };
        Thread threadA = new Thread(run, "A");
        threadA.start();
        Thread.sleep(200);
        flag = false;

    }
}

flag 设置为false以后并不是立刻就停, 而是在修改完flag以后, 在进行下次flag判断的时候才会停止

后台守护线程

在多线程里面可以进行守护线程的定义, 也就是说如果现在主线程的程序或者其他线程还在运行的时候, 那么守护线程一直存在, 并且一直在后台运行

public class Main {
    public static void main(String[] args) throws Exception {

        Runnable run = new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 6; i++) {
                    try {
                        Thread.sleep(100);
                    } catch (Exception e) {}
                    System.out.println(Thread.currentThread().getName() + "正在运行" + i);
                }
            }
        };
        Runnable run2 = new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < Integer.MAX_VALUE; i++) {
                    try {
                        Thread.sleep(100);
                    } catch (Exception e) {}
                    System.out.println(Thread.currentThread().getName() + "正在运行" + i);
                }
            }
        };
        Thread threadA = new Thread(run, "A");
        Thread threadB = new Thread(run2, "守护线程");
        threadB.setDaemon(true);
        threadA.start();
        threadB.start();

    }
}

如果程序执行完毕, 那么守护线程就会消失, 在JVM里最大的守护线程就是GC.

volatile

在正常进行变量处理的时候, 往往会经历如下几个步骤

volatile与synchronized的区别

上一篇下一篇

猜你喜欢

热点阅读