Java线程的建立与使用

1、继承于Thread类

1.建立一个继承于Thread类的子类
2.重写Thread类的run(),将此线程的执行操做声明在run()中
3.建立Thread类的子类的对象
4.经过此对象调用start()java

class MyThread extends Thread {
    @Override
    public void run() {
        for(int i = 0; i < 100; i++) {
            if(i % 2 == 0) {
                System.out.println(Thread.currentThread().getName() + ":" + i);
            }
        }
    }
}
public class ThreadTest {
    public static void main(String[] args) {
        MyThread t1 = new MyThread();
        t1.start();
    }
}

2、Thread的经常使用方法

/**
 * 1.start():启动当前线程:调用当前线程的run()
 * 2.run():一般须要重写Thread类的此方法,将建立的线程要执行的操做声明在此方法中
 * 3.currentThread():静态方法,返回当前代码执行的线程
 * 4.getName():获取当前线程的名字
 * 5.setName():设置当前线程的名字
 * 6.yield():释放当前cpu的执行权,但仍是有可能被分配到
 * 7.join():在线程a中调用线程b的join();此时线程a就进入阻塞状态,直到线程b彻底执行完之后,线程a才结束阻塞状态。
 * 8.stop():强制终止线程
 * 9.sleep(long millitime):让当前线程睡眠指定的millitime 毫秒。在指定的millitime毫秒时间内,当前线程是阻塞状态
 * 10.isAlive():判断当前线程是否活着
 */
class HelloThread extends Thread {
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            if (i % 2 == 0) {
                try {
                    sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + ":" + i);
            }
        }
    }
}

public class ThreadMethodTest {
    public static void main(String[] args) {
        HelloThread hello = new HelloThread();
        hello.setName("线程1");
        hello.start();

        Thread.currentThread().setName("主线程");
        for (int i = 0; i < 100; i++) {
            if (i % 2 == 0) {
                System.out.println(Thread.currentThread().getName() + ":" + i);
            }

            if (i == 20) {
                try {
                    hello.join();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

3、Thread的调度

调度方法:
1.同优先级线程组成先进先出队列,使用时间片策略
2.对高优先级,使用优先调度的抢占式策略
线程优先级:
MAX_PRIORITY:10
MIN_PRIORITY:1
NORM_PRIORITY:5
线程建立时继承父线程的优先级
低优先级只是得到调度的几率低,并不是必定是高优先级线程以后才被调用安全

4、实现Runnable接口

/**
 * 1.建立一个实现了Runnable接口的类
 * 2.实现类去实现Runnable中的抽象方法:run()
 * 3.建立实现类的对象
 * 4,将此对象做为参数传递到Thread类的构造器中,建立Thread类的对象
 * 5.经过Thread类的对象调用start()
 */
class twThread implements Runnable {
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            if (i % 2 == 0) {
                System.out.println(Thread.currentThread().getName() + ":" + i);
            }
        }
    }
}
public class ThreadTest1 {
    public static void main(String[] args) {
        twThread tw = new twThread();
        Thread thread1 = new Thread(tw);
        thread1.start();
    }
}

5、线程的生命周期

线程的状态:
新建:当一个Thread类或其子类的对象被声明并建立时,新生的线程对象处于新建状态。
就绪:处于新建状态的线程被start()后,将进入线程的队列等待CPU时间片,此时它已具有了运行条件,只是没有分配到CPU资源。
运行:当就绪的线程被调度并得到CPU资源时,便进入运行状态,run()方法定义了线程的操做和功能。
阻塞:在某种特殊状况下,被人为挂起或执行输入输出操做时,让出CPU并临时终止本身的执行,进入阻塞状态。
死亡:线程完成了它的所有工做或线程被提早强制性地终止或出现异常致使结束。多线程

6、线程安全

package com.study.thread;

/**
 *  1.出现重票,线程安全问题
 *  2.缘由:当某个线程操做车票过程当中,还没有操做完成时,其余线程进来,也操做车票
 *  3.解决:当一个线程a操做ticket时,其余线程不能进来,直到a操做完ticket时,线程才能够开始操做,ticket,这种状况即便线程a出现了阻塞,也不能被改变
 *  4,在java中经过同步机制,解决线程安全问题
 *  方式一:同步代码块
 *
 *  synchronized(同步监视器) {
 *     // 须要被同步的代码
 *  }
 *说明:1.操做共享数据的代码,即为须要被同步的代码,不能包含代码多了,也很多
 *     2.共享数据:多个线程共同操做的变量,好比ticket
 *     3.同步监视器:俗称锁,任何一个类的对象,均可以充当锁
 *          要求:多个线程必需要用同一把锁
 *          补充:在实现Runnable接口建立多线程方式中,咱们能够考虑使用this充当同步监视器
 *          继承Thread类建立多线程,慎用this当同步监视器,考虑用当前类充当同步监视器
 *  方式二:同步方法
 *  若是操做共享数据的代码完整的声明在一个方法中,咱们不妨将此方法声明同步的
 *
 *  5.同步的方式:解决了线程安全问题
 *   操做同步代码时只能有一个线程参与,其余线程等待,至关于单线程过程,效率低
 */
class Windows implements Runnable {
    private int ticket = 100;
    Object obj = new Object();
    @Override
    public void run() {
        synchronized(obj) {
            while(ticket > 0) {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + ":卖票,票号为" + ticket);
                ticket--;
            }
        }
    }
}
public class WindowTest {
    public static void main(String[] args) {
        Windows w1 = new Windows();
        Thread t1 = new Thread(w1);
        Thread t2 = new Thread(w1);
        Thread t3 = new Thread(w1);
        t1.start();
        t2.start();
        t3.start();
    }
}

JDK5.0新语法ide

class Window implements Runnable {
    private int ticket = 100;
    // 实例化ReentrantLock
    private ReentrantLock lock = new ReentrantLock();

    @Override
    public void run() {
        while (true) {
            try {
                // 调用lock
                lock.lock();
                if (ticket > 0) {
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + "售票,票号为:" + ticket);
                    ticket--;
                } else {
                    break;
                }
            }finally {
                // 解锁
                lock.unlock();
            }


        }
    }
}

public class LockTest {
    public static void main(String[] args) {
        Window window = new Window();

        Thread t1 = new Thread(window);
        Thread t2 = new Thread(window);
        Thread t3 = new Thread(window);
        t1.setName("窗口1");
        t2.setName("窗口2");
        t3.setName("窗口3");

        t1.start();
        t2.start();
        t3.start();
    }
}

7、线程通讯

package com.study.channel;
/**
 * 线程通讯:两个线程交替打印1-100数字
 * 涉及到3个方法
 * wait()一旦执行此方法,当前线程进入阻塞状态,并释放同步监视器
 * notify():一旦执行此方法,就会唤醒被wait()的一个线程,若是有多个线程被wait,就唤醒优先级高的
 * notifyall()一旦执行此方法,就会唤醒全部wait的线程
 *
 * 说明:
 *      这三个方法必须放到同步代码块或同步方法中
 *      这三个方法的调用者必须是同步代码块或同步方法中的同步监视器,不然会出现异常
 * sleep() 和 wait()的异同
 * 相同点:一旦执行方法,  均可以使得当前线程进入阻塞状态
 * 不一样点:
 *      两个方法声明的位置不一样:Thread类中声明sleep()方法,Object类中声明wait()方法
 *      sleep()可在任何场景下调用,wait()必须在同步代码块中调用
 *      若是两个方法都在同步代码块中调用,sleep()不会释放同步监视器,wait()会释放同步监视器(锁)
 *
 */
class Number implements Runnable {
    private int number = 100;

    @Override
    public void run() {
        while (true) {
            synchronized (this) {
                notifyAll();
                if (number >= 1) {
                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + ":" + number);
                    number--;
                    try {
                        // 使得调用以下wait以下方法的线程进入阻塞状态
                        wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                } else {
                    break;
                }
            }
        }
    }
}

public class CommuncationTest {
    public static void main(String[] args) {
        Number num = new Number();
        Thread t1 = new Thread(num);
        Thread t2 = new Thread(num);
        Thread t3 = new Thread(num);
        t1.setName("线程1");
        t2.setName("线程2");
        t3.setName("线程3");

        t1.start();
        t2.start();
        t3.start();
    }
}

8、实现Callable建立多线程

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

/**
 * 比实现Runnable强大
 * 1.支持返回值
 * 2.支持抛异常
 * 3.泛型
 */

// 1. 建立一个实现Callable的实现类
class NumThread implements Callable {
    // 实现call 方法,将线程要作的操做生命在call方法中
    @Override
    public Object call() throws Exception {
        int sum = 0;
        for (int i = 1; i <= 100; i++) {
            if (i % 2 == 0) {
                sum += i;
            }
        }
        return sum;
    }

}

public class ThreadNew {
    public static void main(String[] args) {
        // 3.建立callable 实现类的对象
        NumThread num = new NumThread();
        // 4.将此Callbale 实现类的对象传递到FutureTask构造器中,建立FutureTask对象
        FutureTask futureTask = new FutureTask(num);
        // 5. 将futureTask传入Thread构造器
        new Thread(futureTask).start();
        try {
            // 6. 获取到相应返回值
            Object sum = futureTask.get();
            System.out.println("返回值:" + sum);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }
}

9、线程池建立多线程

package com.study.thread;

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

/**
 * 使用线程池建立线程
 * 好处:
 * 1.提高响应速度,
 * 2.下降资源消耗(重复利用线程池中的线程,不须要每次都建立)
 * 3。便于点成管理
 *      corePloolSize  核心池的大小
 *      maxinumPloolSize  最大线程数
 *      keepAliveTime 线程没有任务时,最多保存多长时间终止
 */
class NumberThread implements Runnable {
    @Override
    public void run() {
        for (int i = 0; i <= 100;i++ ) {
            if(i % 2 == 0) {
                System.out.println(Thread.currentThread().getName() + ":" + i);
            }
        }
    }
}
public class ThreadPool {
    public static void main(String[] args) {
        // 1.提供指定线程数量的线程池
        ExecutorService executorService = Executors.newFixedThreadPool(10);
        //2.执行指定的线程操做,须要提供实现Runnable接口或者Callable 接口实现类的对象
        executorService.execute(new NumberThread()); // 适用于Runnable
//        executorService.submit(Callable callable) // 适用于Callable
        //3.关闭链接池
        executorService.shutdown();

    }
}
相关文章
相关标签/搜索