进程及线程的常用方法
一、进程
进程是系统进行资源分配和调用的独立单元,每一个进程都有它的独立内存空间和系统资源。
二、单进程操作系统和多进程操作系统的区别
1.单进程操作系统:dos(一瞬间只能执行一个任务)
2.多进程单用户操作系统:Windows(一瞬间只能执行多个任务)
3.多进程多用户操作系统:Linux(一瞬间只能执行多个任务)
三、现在的多核CPU是否可以让系统在同一个时刻可以执行多个任务吗?
理论上是可以的
四、线程
1.线程的介绍
1.线程是进程里面的一条执行路径,每个线程同享进程里面的内存空间和系统资源
2.一个进程 可以有 多个线程:各个线程都有不同的分工
2.线程和进程的关系
1.进程 与 进程之间的关系:进程之间的内存空间和系统资源是独立的
2.同一个进程里的多条线程 :线程之间的内存空间和系统资源是共享的
进程中:可以有一条或一条以上的线程
进程里只有一条线程的情况下,这条线程就叫做主线程
进程里有多条线程的情况下,主线程只有一条线程
注意:线程是在进程里的,他们是包含关系
五、我们应用的软件有哪些是多线程的应用
微信、QQ、支付宝、淘宝等等都是
六、Java中编写多线程
1.创建线程的方式 – 线程类
1.创建线程类:
1.创建类 – MyThread
2.继承Thread
3.重写run方法
2.启动线程:
1.创建线程类的对象:MyThread t = new MyThread();
2.启动线程:t.start();
public class Test01 {
public static void main(String[] args) {
//创建子线程
MyThread t = new MyThread();
//启动线程
t.start();
}
}
public class MyThread extends Thread{
//线程对象抢到CPU资源后才调用的方法
//run方法的作用:该线程的功能都是编写在run方法中
@Override
public void run() {
System.out.println("调用MyThread中的run()");
}
}
2.创建线程的方式 – 任务类
1.创建任务类:
1.创建Task类
2.实现Runnable接口
3.重写run方法
2.启动线程:
1.创建线程对象:Thread t = new Thread(new Task());
2.启动线程:t.start();
public class Test01 {
public static void main(String[] args) {
//创建子线程(并将任务对象交给线程)
Thread t = new Thread(new Task());
//启动线程
t.start();
}
}
//任务类
public class Task implements Runnable {
//线程对象抢到CPU资源后调用的方法
//run方法的作用:该线程的功能都是编写在run方法中
@Override
public void run() {
System.out.println("调用Task类中的run()");
}
}
七、感受多线程之间争抢资源的场景
需求:编写一个多线程的应用程序,主线程打印1-100之间的数字,子线程打印200-300之间的数字,观察其输出的结果,体会多线程互相争抢资源的场景
public class Test01 {
public static void main(String[] args) {
MyThread t = new MyThread();
t.start();//启动线程 -- 启动后,主线程抢到资源后代码就会向下执行
for (int i = 1; i <= 100; i++) {
System.out.println("主线程:" + i);
}
}
}
public class MyThread extends Thread{
@Override
public void run() {
for (int i = 200; i <=300; i++) {
System.out.println("子线程:" + i);
}
}
}
八、线程的优先级别
需求:在主线程中创3个子线程,并且设置不同优先级,观察其优先级对线程执行结果的”影响”。
public class Test01 {
public static void main(String[] args) {
A a = new A();
B b = new B();
C c = new C();
//设置优先级别
a.setPriority(Thread.MAX_PRIORITY);//10
b.setPriority(Thread.NORM_PRIORITY);//5
c.setPriority(Thread.MIN_PRIORITY);//1
a.start();
b.start();
c.start();
}
}
public class A extends Thread{
@Override
public void run() {
for (int i = 1; i <= 500; i++) {
System.out.println("A:" + i);
}
}
}
public class B extends Thread{
@Override
public void run() {
for (int i = 1; i <= 500; i++) {
System.out.println("B:" + i);
}
}
}
public class C extends Thread {
@Override
public void run() {
for (int i = 1; i <= 500; i++) {
System.out.println("C:" + i);
}
}
}
九、线程的命名
1.方案一
public class Test01 {
public static void main(String[] args) {
MyThread a = new MyThread("A");
MyThread b = new MyThread("B");
MyThread c = new MyThread("C");
//设置优先级别
a.setPriority(Thread.MAX_PRIORITY);//10
b.setPriority(Thread.NORM_PRIORITY);//5
c.setPriority(Thread.MIN_PRIORITY);//1
a.start();
b.start();
c.start();
}
}
public class MyThread extends Thread{
private String threadName;
public MyThread(String threadName) {
this.threadName = threadName;
}
@Override
public void run() {
for (int i = 1; i <= 500; i++) {
System.out.println(threadName + ":" + i);
}
}
}
2.方案二
public class Test01 {
public static void main(String[] args) {
MyThread a = new MyThread("A");
MyThread b = new MyThread("B");
MyThread c = new MyThread("C");
//设置优先级别
a.setPriority(Thread.MAX_PRIORITY);//10
b.setPriority(Thread.NORM_PRIORITY);//5
c.setPriority(Thread.MIN_PRIORITY);//1
a.start();
b.start();
c.start();
}
}
public class MyThread extends Thread {
public MyThread(String name){
super(name);
}
@Override
public void run() {
// 获取当前线程的对象
Thread thread = Thread.currentThread();
for (int i = 1; i <=500; i++) {
System.out.println(thread.getName() + ":" + i);
}
}
}
十、线程休眠
1.Thread.sleep(1000); – Thread类的静态方法
2.该方法写在哪个线程中,哪个线程就休眠(进入到阻塞状态)
需求:编写一个抽取学员回答问题的程序,要求倒数三秒后输出被抽中的学员姓名
import java.util.Random;
public class Test01 {
public static void main(String[] args) throws InterruptedException{
String[] names = {"孙权","周瑜","大乔","小乔","诸葛瑾"};
Random ran = new Random();
int index = ran.nextInt(names.length);
for (int i = 3; i > 0; i--) {
System.out.println(i);
Thread.sleep(1000);
}
System.out.println(names[index]);
}
}
十一、线程的礼让
需求:创建两个线程A,B,分别各打印1-100的数字,其中B一个线程,每打印一次,就礼让一次,观察实验结果
public class Test01 {
public static void main(String[] args) {
A a = new A();
B b = new B();
a.start();
b.start();
}
}
public class A extends Thread{
@Override
public void run() {
for (int i = 1; i <= 100 ; i++) {
System.out.println("A:" + i);
}
}
}
public class B extends Thread {
@Override
public void run() {
for (int i = 1; i <= 100 ; i++) {
System.out.println("B:" + i);
//礼让:让当前线程退出CPU资源,马上又进入到抢资源的状态
Thread.yield();
}
}
}
十二、线程的合并
需求:主线程和子线程各打印200次,从1开始每次增加1,当主线程打印到10之后,
让子线程先打印完再打印主线程
public class Test01 {
public static void main(String[] args) throws InterruptedException{
MyThread t = new MyThread();
t.start();
for (int i = 1; i <=200; i++) {
System.out.println("主线程:" + i);
if (i == 10) {
//合并
t.join();
}
}
}
}
public class MyThread extends Thread{
@Override
public void run() {
for (int i = 1; i <= 200; i++) {
System.out.println("子线程:" + i);
}
}
}
十三、线程的中断
使用MyThread中的flag属性去控制
1.方案一
public class Test01 {
public static void main(String[] args) throws InterruptedException{
MyThread t = new MyThread();
t.start();
Thread.sleep(3000);
//立即中断线程
//t.stop();//淘汰使用
t.setFlag(false);
}
}
public class MyThread extends Thread{
private boolean flag = true;
public void setFlag(boolean flag) {
this.flag = flag;
}
@Override
public void run() {
while(flag){
System.out.println("111");
System.out.println("222");
System.out.println("333");
System.out.println("444");
}
}
}
2.方案二
public class Test01 {
public static void main(String[] args) throws InterruptedException{
MyThread t = new MyThread();
t.start();
Thread.sleep(3000);
//改变线程状态
t.interrupt();
}
}
public class MyThread extends Thread{
@Override
public void run() {
Thread thread = Thread.currentThread();
while (!thread.isInterrupted()) {//判断当前线程是否中断
System.out.println("111");
System.out.println("222");
System.out.println("333");
System.out.println("444");
}
}
}
十四、守护线程
含义:守护线程默默守护着前台线程,当所有前台线程都死亡时,守护线程就会自动死亡
注意:垃圾回收器就是守护线程
t.setDaemon(true);
public class Test01 {
public static void main(String[] args) throws InterruptedException{
MyThread t = new MyThread();
t.setDaemon(true);
t.start();
for (int i = 1; i <=5; i++) {
System.out.println("主线程:" + i);
Thread.sleep(1000);
}
}
}
//做实验
//父类方法如果不抛异常,子类重写时就不能抛异常,必须try...catch...
class A{
public void method(){}
}
class B extends A{
@Override
public void method(){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class MyThread extends Thread{
@Override
public void run() {
while (true) {
System.out.println("守护线程正在守护着前台线程");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
十五、线程局部变量(实现线程范围内的共享变量)
1.共享单个数据
public class Test01 {
public static void main(String[] args) {
//线程1
new Thread(new Runnable() {
@Override
public void run() {
int i = 10;
//存储数据
Container.map.put(Thread.currentThread(),i);
A a = new A();
B b = new B();
a.println();//线程1中的A类对象输出:10
b.println();//线程1中的B类对象输出:10
}
},"线程1").start();
//线程2
new Thread(new Runnable() {
@Override
public void run() {
int i = 20;
//存储数据
Container.map.put(Thread.currentThread(),i);
A a = new A();
B b = new B();
a.println();//线程2中的A类对象输出:20
b.println();//线程2中的B类对象输出:20
}
},"线程2").start();
}
}
import java.util.concurrent.ConcurrentHashMap;
public class Container {
public static final ConcurrentHashMap<Thread, Integer> map = new ConcurrentHashMap<>();
}
public class A {
public void println(){
Thread thread = Thread.currentThread();
Integer value = Container.map.get(thread);
System.out.println(thread.getName() + "中的A类对象输出:" + value);
}
}
public class B {
public void println(){
Thread thread = Thread.currentThread();
Integer value = Container.map.get(thread);
System.out.println(thread.getName() + "中的B类对象输出:" + value);
}
}
2.共享多个数据
public class Test01 {
public static void main(String[] args) {
//线程1
new Thread(new Runnable() {
@Override
public void run() {
Data data = new Data("xxx",10);
//存储数据
Container.map.put(Thread.currentThread(),data);
A a = new A();
B b = new B();
a.println();//线程1中的A类对象输出:10
b.println();//线程1中的B类对象输出:10
}
},"线程1").start();
//线程2
new Thread(new Runnable() {
@Override
public void run() {
Data data = new Data("yyy",20);
//存储数据
Container.map.put(Thread.currentThread(),data);
A a = new A();
B b = new B();
a.println();//线程2中的A类对象输出:20
b.println();//线程2中的B类对象输出:20
}
},"线程2").start();
}
}
import java.util.concurrent.ConcurrentHashMap;
public class Container {
public static final ConcurrentHashMap<Thread, Data> map = new ConcurrentHashMap<>();
}
public class A {
public void println(){
Thread thread = Thread.currentThread();
Data value = Container.map.get(thread);
System.out.println(thread.getName() + "中的A类对象输出:" + value);
}
}
public class B {
public void println(){
Thread thread = Thread.currentThread();
Data value = Container.map.get(thread);
System.out.println(thread.getName() + "中的B类对象输出:" + value);
}
}
3.使用ThreadLocal的技术
public class Test01 {
public static void main(String[] args) {
//线程1
new Thread(new Runnable() {
@Override
public void run() {
Data data = Data.getInstance("xxx",10);
//存储数据
Container.local.set(data);
A a = new A();
B b = new B();
a.println();//线程1中的A类对象输出:10
b.println();//线程1中的B类对象输出:10
}
},"线程1").start();
new Thread(new Runnable() {
@Override
public void run() {
Data data = Data.getInstance("yyy",20);
Container.local.set(data);
A a = new A();
B b = new B();
a.println();//线程2中的A类对象输出:20
b.println();//线程2中的B类对象输出:20
}
},"线程2").start();
}
}
//容器类
public class Container {
public static final ThreadLocal<Data> local = new ThreadLocal<>();
}
public class A {
public void println(){
Thread thread = Thread.currentThread();
Data value = Container.local.get();
System.out.println(thread.getName() + "中的A类对象输出:" + value);
}
}
public class B {
public void println(){
Thread thread = Thread.currentThread();
Data value = Container.local.get();
System.out.println(thread.getName() + "中的B类对象输出:" + value);
}
}