并发
大家可能已经很熟悉操作系统中的多任务(multitasking): 在同一刻运行多个程序的能力。 例如,在编辑或下载邮件的同时可以打印文件,说简单点就是同一时间同时做多件事。今天,人们很可能有单台拥有多个 CPU 的 计算机,但是,并发执行的进程数目并不是由 CPU 数目制约的。操作系统将 CPU 的时间片 分配给每一个进程, 给人并行处理的感觉。
多线程程序在较低的层次上扩展了多任务的概念:一个程序同时执行多个任务。通常, 每一个任务称为一个线程(thread), 它是线程控制的简称。可以同时运行一个以上线程的程 序称为多线程程序(multithreaded)。
什么是进程呢?
进程是指运行中的应用程序,每个进程都有自己独立的地址空间(内存空间),比如用户点击桌面的IE浏览器,就启动了一个进程,操作系统就会为该进程分配独立的地址空间。当用户再次点击左面的IE浏览器,又启动了一个进程,操作系统将为新的进程分配新的独立的地址空间。目前操作系统都支持多进程。
什么是线程
是进程中的一个实体,是被系统独立调度和分派的基本单位,线程自己不拥有系统资源,只拥有一点在运行中必不可少的资源,但它可与同属一个进程的其它线程共享进程所拥有的全部资源。一个线程可以创建和撤消另一个线程,同一进程中的多个线程之间可以并发执行。线程有就绪、阻塞和运行三种基本状态。
多进程与多线程有哪些区别呢?
本质的区别在于每个进程拥有自己的一整套变 量, 而线程则共享数据。 这听起来似乎有些风险, 的确也是这样, (在后续更新将可以看到这个问题)。然而,共享变量使线程之间的通信比进程之间的通信更有效、更容易。此外, 在有 些操作系统中,与进程相比较, 线程更“ 轻量级”, 创建、撤销一个线程比启动新进程的开 销要小得多。
在实际应用中, 多线程非常有用。例如, 一个浏览器可以同时下载几幅图片。一个 Web 服务器需要同时处理几个并发的请求。图形用户界面(GUI) 程序用一个独立的线程从宿主 操作环境中收集用户界面的事件。
用java实现一个线程
java实现线程有两种办法:
第一种:
通过继承方式实现:继承Thread类重写run方法
/**
* 继承Thread类的方式创建线程
* @author Administrator
*
*/
public class MyThread extends Thread{
//重写run()方法
public void run(){
for(int i=0;i<100;i++){
//Thread.currentThread().getName()获取当前线程的名字
System.out.println(Thread.currentThread().getName()+":"+i);
}
}
}
采用继承方式启动线程
package ThreadDemo2;
public class Test {
public static void main(String[] args) {
MyThread t1 = new MyThread();
MyThread t2 = new MyThread();
/* t1.start(); //启动线程
t2.start();*/
t1.run();
t2.run(); //1.只有主线程一条执行路径 2.依次调用了两次run()方法
}
}
第二种:
通过实现Runnable接口实现多线程
package ThreadDemo3;
/**
* 实现Runnable接口方式创建线程
* @author Administrator
*
*/
public class MyRunnable implements Runnable{
@Override
public void run() {
for(int i=0;i<100;i++){
System.out.println(Thread.currentThread().getName()+":"+i);
}
}
}
采用实现Runnable接口方式启动线程
package ThreadDemo3;
public class Test {
public static void main(String[] args) {
//1.创建线程对象
Runnable myRunnable = new MyRunnable();
Thread t = new Thread(myRunnable,"MyThread");
t.start(); //2.启动线程
}
}
两种实现方式都能实现多线程,但是更推荐第二种实现Runnable接口的方式,他有如下优点:
1、可以利用java的多实现
2、可以利用java8更新的lambda表达式实现函数式编程
如下:
public static void main(String[] args) {
// lambda表达式创建线程
Runnable r = () -> {
for (int i = 0; i < 100; i++) {
System.out.println("i:" + i);
}
};
//启动线程
new Thread(r).start();
new Thread(r).start();
}
线程的异常处理
线程的 run方法不能抛出任何受查异常, 但是,非受査异常会导致线程终止。在这种情 况下,线程就死亡了。
未捕获异常处理器
不需要任何 catch子句来处理可以被传播的异常。相反,就在线程死亡之前, 异 常被传递到一个用于未捕获异常的处理器。 该处理器必须属于一个实现 Thread.UncaughtExceptionHandler 接口的类。这个接口只有— 个方法。
public static void main(String[] args) {
// TODO Auto-generated method stub
//lambda表达式方式创建线程
Runnable r = () -> {
for (int i = 0; i < 100; i++) {
try {
//当前线程睡10毫秒
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
int a = 1 / 0;
}
};
Thread t = new Thread(r);
t.setName("当前线程");
//采用匿名类的方式创建UncaughtExceptionHandler对象
t.setUncaughtExceptionHandler(new UncaughtExceptionHandler() {
//编写实现
public void uncaughtException(Thread t, Throwable e) {
// TODO Auto-generated method stub
System.out.println("处理了");
System.out.println(t.getName());
e.printStackTrace();
}
});
//启动线程
t.start();
}
void uncaughtException(Thread t, Throwable e) 可以用 setUncaughtExceptionHandler方法为任何线程安装一个处理器。也可以用 Thread 类的静态方法 setDefaultUncaughtExceptionHandler 为所有线程安装一个默认的处理器。替换 处理器可以使用日志 API 发送未捕获异常的报告到日志文件。 如果不安装默认的处理器, 默认的处理器为空。但是, 如果不为独立的线程安装处理 器,此时的处理器就是该线程的 ThreadGroup 对象。
提示: 线程组是一个可以统一管理的线程集合。默认情况下,创建的所有线程属于相同的线程组, 但是, 也可能会建立其他的组。现在引入了更好的特性用于线程集合的操作, 所以建议不要在自己的程序中使用线程组。
线程之间的调度
等待和通知
等待[wait()]和通知[notify(),notifyAll()]提供了在同一对象上同步的线程之间进行通信的方式。
说明:
wait()方法:当在一个对象上调用wait()方法时,执行该代码的线程立即放弃对该对象的锁定并将该线程移动到等待状态。
notify()方法:这会唤醒在同一对象上调用wait()的线程,并将线程移动到就绪状态。
notifyAll()方法:这会唤醒在同一个对象上调用wait()的所有线程。
运行和让步
Yield()方法用于为具有相同优先级的其他线程提供执行机会,即让当前运行的线程移动到可运行状态。
睡眠和启用
nSleep()方法用于暂停线程一段指定的时间,即将当前运行的线程移动到Sleep状态一段指定的时间,然后再将其移动到runnable状态。例:
Thread.sleep(毫秒数);
线程优先级
每个线程都有一个优先级,优先级由1到10之间的整数数字表示,数字越高,优先级越高,线程优先级默认为5。在大多数情况下,线程调度程序根据线程的优先级(称为抢占式调度)来调度线程。
线程生产者和消费者问题
直接上代码了这样更直接:
链接:https://pan.baidu.com/s/11nDWjnWjI5epmNUKGB8vGw
提取码:viub
使用方式解压导入IDE即可
* ┏┓ ┏┓+ +
* ┏┛┻━━━┛┻┓ + +
* ┃ ┃
* ┃ ━ ┃ ++ + + +
* ████━████ ┃+
* ┃ ┃ +
* ┃ ┻ ┃
* ┃ ┃ + +
* ┗━┓ ┏━┛
* ┃ ┃
* ┃ ┃ + + + +
* ┃ ┃ Code is far away from bug with the animal protecting
* ┃ ┃ + 神兽保佑,代码无 bug
* ┃ ┃
* ┃ ┃ +
* ┃ ┗━━━┓ + +
* ┃ ┣┓
* ┃ ┏┛
* ┗┓┓┏━┳┓┏┛ + + + +
* ┃┫┫ ┃┫┫
* ┗┻┛ ┗┻┛+ + + +
更多内容后续更新。。。