Java多线程编程(1)

1、进程和线程

串行和并行

串行是指多个任务时,各个任务按顺序执行,完成一个之后才能进行下一个。

并行指的是多个任务可以同时执行。异步是多个任务并行的前提条件。

并行和并发

多个cpu实例或者多台机器同时执行一段处理逻辑,是真正的同时。

通过cpu调度算法,让用户看上去同时执行,实际上从cpu操作层面不是真正的同时。

进程和线程

进程具有独立的执行环境。 进程具有一套完整的私有基本运行时资源。 每个进程都有自己的存储空间。

线程有时称为轻量级进程。 创建新线程所需的资源少于创建新进程的资源。

线程状态

初始(NEW):新创建了一个线程对象,但还没有调用start()方法。

运行(RUNNABLE):Java线程中将就绪(ready)和运行中(running)两种状态笼统的称为“运行”。

阻塞(BLOCKED):表示线程阻塞于锁。

等待(WAITING):进入该状态的线程需要等待其他线程做出一些特定动作(通知或中断)。

超时等待(TIMED_WAITING):该状态不同于WAITING,它可以在指定的时间后自行返回。

终止(TERMINATED):表示该线程已经执行完毕。

2、线程对象

线程定义:实现Runnable接口

提供一个Runnable对象。该 Runnable接口定义了一个方法,run用于包含在线程中执行的代码。该Runnable对象将传递给Thread构造函数。

public class HelloRunnable implements Runnable {

    public void run() {
        System.out.println("HelloRunnable");
    }

    public static void main(String args[]) {
        Runnable runnable = new HelloRunnable();
        Thread thread = new Thread(runnable);
        thread.start();
    }

}

线程定义:继承Thread类

子类Thread。在Thread类自身实现Runnable,但其run方法不起作用。应用程序可以子类Thread提供自己的实现run。

public class HelloThread extends Thread {

    public void run() {
        System.out.println("HelloThread");
    }

    public static void main(String args[]) {
        HelloThread helloThread = new HelloThread();
        helloThread.start();
    }

}

线程命名

所有的线程程序的执行,每一次都是不同的运行结果,如果要想区分每一个线程,那么久必须依靠线程的名字。对于线程的名字一般而言会在启动之前进程定义,不建议对已经启动的线程,进行更改名称,或者为不同线程设置重名的情况。

public class HelloRunnableName implements Runnable {
    @Override
    public void run() {
        System.out.println("你好:" + Thread.currentThread().getName());
    }

    public static void main(String[] args) {
        HelloRunnableName helloRunnable = new HelloRunnableName();
        Thread thread = new Thread(helloRunnable, "线程1");
        System.out.println("线程名称:" + thread.getName());
        thread.start();
    }
}
public class HelloThreadName extends Thread {
    public HelloThreadName(String name) {
        // super(name);
        this.setName(name);
    }
    @Override
    public void run() {
        super.run();
        System.out.println("你好:" + Thread.currentThread().getName());
    }
    public static void main(String[] args) {
        HelloThreadName helloThreadName = new HelloThreadName("线程1");
        System.out.println("线程名称:" + helloThreadName.getName());
        helloThreadName.start();
    }
}

线程优先级

线程优先级的范围是1~10,默认的优先级是5。10极最高。 “高优先级线程”被分配CPU的概率高于“低优先级线程”。

public class ThreadPriority implements Runnable {
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.println("线程名称:"
                    + Thread.currentThread().getName()
                    + ",线程优先级:"
                    + Thread.currentThread().getPriority()
                    + ",循环:" + i);
        }
    }
    public static void main(String[] args) {
        ThreadPriority threadPriority = new ThreadPriority();
        Thread thread1 = new Thread(threadPriority);
        thread1.setName("线程1");
        thread1.setPriority(Thread.MIN_PRIORITY);
        Thread thread2 = new Thread(threadPriority);
        thread2.setName("线程2");
        thread2.setPriority(Thread.MAX_PRIORITY);
        thread1.start();
        thread2.start();
    }
}

线程休眠:sleep方法

Thread.sleep使当前线程在指定时间段内暂停执行。这是使处理器时间可用于应用程序的其他线程或计算机系统上可能正在运行的其他应用程序的有效方法。

public class ThreadSleep implements Runnable {
    @Override
    public void run() {
        String info[] = {
                "春眠不觉晓",
                "处处闻啼鸟",
                "夜来风雨声",
                "花落知多少"
        };
        for (int i = 0; i < info.length; i++) {
            System.out.println(info[i]);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    public static void main(String[] args) {
        ThreadSleep threadSleep = new ThreadSleep();
        Thread thread = new Thread(threadSleep);
        thread.start();
    }
}

线程礼让:yield方法

Thread类中提供了一种礼让方法,使用yield()方法表示,它只是给当前正处于运行状态下的线程一个提醒,告知它可以将资源礼让给其他线程,但这仅仅是一种暗示,没有任何一种机制保证当前线程会将资源礼让。 yield()方法使具有同样优先级的线程有进入可执行状态的机会,当当前线程放弃执行权时会再度回到就绪状态。

public class ThreadYield implements Runnable {

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + "开始了");
        Thread.yield();
        System.out.println(Thread.currentThread().getName() + "结束了");
    }

    public static void main(String[] args) {
        ThreadYield threadYield = new ThreadYield();
        Thread thread1 = new Thread(threadYield, "线程1");
        Thread thread2 = new Thread(threadYield, "线程2");
        thread1.start();
        thread2.start();
    }
}

线程联合:join方法

join方法允许一个线程等待另一线程的完成。如果t是Thread正在执行其线程的对象, t.join(); 导致当前线程暂停执行,直到t的线程终止。重载join允许程序员指定等待时间。但是,与一样sleep,join依赖于OS进行计时,因此不应该假定join它将完全按照您指定的时间等待。

public class ThreadJoin implements Runnable {
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println("子线程" + i);
        }
    }
    public static void main(String[] args) {
        ThreadJoin threadJoin = new ThreadJoin();
        Thread thread = new Thread(threadJoin);
        thread.start();
        for (int i = 0; i < 100; i++) {
            System.out.println("主线程main" + i);
            if(i == 90) {
                try {
                    thread.join();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

线程停止

停止一个线程通常意味着在线程处理任务完成之前停掉正在做的操作,也就是放弃当前的操作。 在 Java 中有以下 3 种方法可以终止正在运行的线程: 使用退出标识,使得线程正常退出,即当run方法完成后进程终止。 使用stop强行中断线程(此方法为作废过期方法),不推荐使用。 使用interrupt方法中断线程,不推荐使用。

public class ThreadStop implements Runnable {

    private boolean flag = true;

    @Override
    public void run() {
        int i = 0;
        while (flag) {
            System.out.println("子线程" + i++);
        }

    }

    public void stop() {
        this.flag = false;
    }
    public static void main(String[] args) {
        ThreadStop threadStop = new ThreadStop();
        Thread thread = new Thread(threadStop);
        thread.start();
        for (int i = 0; i < 100; i++) {
            System.out.println("主线程main" + i);
            if (i == 90) {
                threadStop.stop();
                System.out.println("子线程停止了");
            }
        }
    }
}

守护线程

Java线程分为两种:用户线程和守护线程。 用户线程可以认为是系统的工作线程,它会完成这个程序要完成的业务员操作。 守护线程是一种特殊的线程,就和它的名字一样,它是系统的守护者,在后台默默完成一些系统性的服务,比如垃圾回收线程。 如果用户线程全部结束,则意味着这个程序无事可做。守护线程要守护的对象已经不存在了,那么整个应用程序就结束了。

public class ThreadDaemon {
    public static void main(String[] args) {
        Daemon daemon = new Daemon();
        Thread thread1 = new Thread(daemon);
        thread1.setDaemon(true);
        thread1.start();
        Me me = new Me();
        Thread thread2 = new Thread(me);
        thread2.start();
    }
}
class Me implements Runnable {
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println("我的努力奔跑" + i);
        }
    }
}
class Daemon implements Runnable {
    @Override
    public void run() {
        int i = 0;
        while (true) {
            System.out.println("我的守护你" + i++);
        }
    }
}

龟兔赛跑

public class Race implements Runnable {
    private static String winner;
    @Override
    public void run() {
        for (int i = 1; i <= 100; i++) {
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            if ("兔子".equals(Thread.currentThread().getName()) && i % 10 == 0) {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            boolean flag = gameOver(i);
            if (flag) { break; }
            System.out.println(Thread.currentThread().getName() + "跑了" + i + "米");
        }
    }
public boolean gameOver(int meters) {
        if (winner != null) {
            return true;
        }
        if (meters >= 100) {
            winner = Thread.currentThread().getName();
            System.out.println("胜利者是" + winner);
            return true;
        }
        return false;
    }
    public static void main(String[] args) {
        Race race = new Race();
        Thread thread1 = new Thread(race, "乌龟");
        thread1.start();
        Thread thread2 = new Thread(race, "兔子");
        thread2.start();
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章