目录
一.线程与创建线程方式简介
线程与进程的区别:
1、一个进程至少包含一个线程
2、比如电脑上QQ,运行起来就是一个进程,QQ可以聊天同时也可以传文件,聊天和传文件就是两个不同的线程。
软件必须运行起来才算进程。
对于同一个CPU来讲,在某一刻,只能执行一个线程,多个线程频发切换,给人一种多线程操作的假象。
多线程之间存在相互抢占CPU资源的情况。
创建线程的四种方式:
1、Thread 继承
2、实现Runnable 接口
3、Callable 接口
4、使用线程池
二.Thread继承
代码如下:
class MyThread extends Thread{
// Ctrl + o
// 展示所有的可以重写的方法
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("数据:"+i);
}
}
}
public class _01继承Thread类{
public static void main(String[] args) {
// 在Main方法中,启动了一个子线程,子线程什么时候工作
MyThread thread = new MyThread();
thread.start();// 启动一个线程,调用start方法,不要调用run方法
// 一个线程类,是可以创建多个不同的子线程的
MyThread thread2 = new MyThread();
thread2.start();// 启动一个线程,调用start方法,不要调用run方法
// 主线程,直接运行代码 会出现子线程和主线程抢占资源的情况
for (int i = 10; i < 100; i++) {
System.err.println("Main:"+i);
}
}
}
运行结果:
三.实现Runnable接口
代码:
class A implements Runnable{
@Override
public void run() {
for (int i = 0; i < 1000; i++) {
System.out.println(Thread.currentThread().getName()+":"+i);
}
}
}
public class _02Runnable接口 {
/**
* 多线程创建的第二种方式,使用 Runnable接口
* 该接口还需要传递给Thread类才能启动,否则自己启动不了
*
* 两种方式:推荐使用第二种
* 1、Thread类是一个线程类,它只需要管理好线程就行了,不需要管业务怎么写
* 2、具体的业务可以交给Runnable接口实现
* 3、java是单继承的,继承了Thread,就无法继承别的类了,但是可以实现多个接口。
*/
public static void main(String[] args) {
A a = new A();
new Thread(a).start();
// Runnable接口本身就是一个函数式接口,就可以使用lambda表达式,代码可以简化为如下:
new Thread( ()-> {
for (int i = 0; i < 1000; i++) {
System.out.println(Thread.currentThread().getName()+":"+i);
}
}).start();
for (int i = 0; i < 1000; i++) {
System.err.println(Thread.currentThread().getName()+":"+i);
}
}
}
运行结果:
四.Callable接口
代码:
class MyCall implements Callable<Integer>{
@Override
public Integer call() throws Exception {
return 200;
}
}
class MyRun implements Runnable{
@Override
public void run() {
System.out.println("我是子线程....");
}
}
public class _03Callable接口 {
public static void main(String[] args) throws ExecutionException, InterruptedException {
FutureTask<Integer> futureTask = new FutureTask<>(new MyCall());
new Thread(futureTask,"计算线程").start();
Integer i = futureTask.get();
System.out.println(i);
// --------------------------------------
new Thread(new MyRun()).start();
// ------------------使用callable 模拟 子线程进行大量计算并返回结果------------------
FutureTask<Integer> f1 = new FutureTask<>(
()->{
System.out.println(Thread.currentThread().getName()+" come in callable");
TimeUnit.SECONDS.sleep(4);
return 1024;
}
);
FutureTask<Integer> f2 = new FutureTask<>(
()->{
System.out.println(Thread.currentThread().getName()+" come in callable");
TimeUnit.SECONDS.sleep(4);
return 2048;
}
);
new Thread(f1,"线程一:").start();
new Thread(f2,"线程二:").start();
while(!f1.isDone()){
System.out.println("f1 wait中.....");
}
while(!f2.isDone()){
System.out.println("f2 wait中.....");
}
// 其实 get 获取不到值会一直阻塞,直到获取到值为止
int a = f1.get();
int b = f2.get();
System.out.println(a+b);
}
}
运行结果:
五.使用线程池
代码:
public class _04线程池 {
public static void main(String[] args) {
ExecutorService threadPool = new ThreadPoolExecutor(
2,
5,
2L,
TimeUnit.SECONDS,
new ArrayBlockingQueue<Runnable>(3),
Executors.defaultThreadFactory(),
//new ThreadPoolExecutor.AbortPolicy()
//new ThreadPoolExecutor.CallerRunsPolicy()
//new ThreadPoolExecutor.DiscardOldestPolicy()
new ThreadPoolExecutor.DiscardOldestPolicy()
);
//10个顾客请求
try {
for (int i = 1; i <= 10; i++) {
threadPool.execute(() -> {
System.out.println(Thread.currentThread().getName() + "\t 办理业务");
});
}
} catch (Exception e) {
e.printStackTrace();
} finally {
threadPool.shutdown();
}
}
}
运行结果: