1. 进程: 是一个独立运行的应用程序
比如电脑软件,启动起来以后,就是一个进程 进程需要电脑进行分配(可以参考任务管理器)可以获取当前系统内存 网卡 显卡等
1.独立性:
各个进程之间是互相独立的,互相不影响
2.互斥性:
每个应用程序(软件)系统分配一个独立的端口号 如果一个软件 qq端 口号是97 idea端口也叫97
写代码时 Demo01 里面main主函数 Demo01可以看成是一个应用程序 就是一个进程
2.线程【重点】
进程是有至少一个或者多个线程组成的。
线程是进程最小的基本单位。
特性:
1.抢占式运行【重要】
给程序分配CPU时,按照时间片来执行,单位时间片抢占式执行的
随机抢占
2.资源共享
同一个进程里面 ,有多个线程 ,这个多个线程可以共享一个数据
java程序:Demo1可以看成一个进程
一个java程序中有两个线程:
1.main主程序 2.垃圾回收的线程
3.并行和并发
并行:真正的同时进行
并发:同时发生,轮流交替执行
4.创建线程的两种方式
java虚拟机允许应用程序同时执行多个执行线程。
创建线程的一种:
创建一个新的执行线程的两种方法。
一个是将一个类声明为Thread的子类,这个子类需要重写run方法Thread。然后可以分配并启动子类的实例。
练习:新建两个线程,一个打印99乘法表,另一个打印直角三角形
package com.xiancheng.test; class A extends Thread{ @Override public void run() { System.out.println("九九乘法表如下:"); for (int i = 1 ; i < 10 ; i++) { for (int j = 1 ; j <= i ; j++){ System.out.print(j + "*" + i + "=" + i*j + "\t"); } System.out.println(); } } } class B extends Thread{ @Override public void run() { System.out.println("直角三角形"); for (int i = 1 ; i < 10 ; i++) { for (int j = 1 ; j <= i ; j++){ System.out.print("*"); } System.out.println(); } } } public class Demo02 { public static void main(String[] args) { new A().start(); new B().start(); } }
第二种创建方式:
另一种方法来创建一个线程是 声明实现类Runnable接口,那个类然后实现了run方法,然后可以分配类的实例,在创建Thread时作为参数传递,并启动。
package com.xiancheng.test; //练习:新建一个线程,一个线程打印99乘法表,另外一个线程打印直接三角形 public class Demo04 { public static void main(String[] args) { new Thread(new Runnable() { @Override public void run() { for (int i = 1; i < 10; i++) { for (int j = 1; j <= i ; j++) { System.out.print(i + "*" + j + "=" + i*j + "\t"); } System.out.println(); } } }).start(); new Thread(new Runnable() { @Override public void run() { for (int i = 1; i < 8; i++) { for (int j = 1; j <= i; j++) { System.out.print("* "); } System.out.println(); } } }).start(); } }
开发中常用第二种方式:实现Runnable接口 ,而不是第一种继承Thread
5.线程同步和锁
构造方法:
Thread() 分配一个新的Thread对象
Thread(Runnable target) 分配一个新的Thread对象,第二种创建的形式
Thread(Runnable target , String name) :
分配一个新的Thread对象,并 对这个线程起一个名字
strtic Thread | currentThread()返回对当前正在执行的线程对象的引用 |
---|---|
String | getName()返回此线程的名称 |
void | steName(String name) 将此现成的名称更改为等于参数name |
package com.xiancheng.gouzhao; class MyThread1 implements Runnable{ @Override public void run() { Thread thread = Thread.currentThread(); System.out.println(thread.getName()); } } class MyThread2 implements Runnable{ @Override public void run() { Thread thread = Thread.currentThread(); System.out.println(thread.getName()); } } public class Demo01 { public static void main(String[] args) { //常规流程 Thread thread = Thread.currentThread();//获取当前线程对象 System.out.println(thread.getName());//获取当前线程的名字 main //获取thread2的当前线程对象 Thread thread2 = new Thread(new MyThread2() , "大黄"); thread2.start();//大黄 System.out.println(thread2.getName());//大黄 //简化流程 new Thread(new MyThread1() , "二狗").start(); } }
线程下面的方法:
int | getPriority()返回此线程的优先级 |
---|---|
void | setPriority(int newPriority)更改此线程的优先级 |
6.线程同步和锁
当多个线程同时请求一个数据的时候,会导致数据不准确的情况。相互之间出现问题,容易出现线程安全问题。比如多个线程操作同一个数据,都打算修改商品库存
线程的同步真实的意思:让你“排队”,几个线程之间要排队。轮流对共享资源进行操作,等一个结束后,另一个在进行操作。
变量:是唯一的,是准确的
同步代码块: 将一段代码放到synchronized 然后括起来。就会对这段代码加上锁
synchronized (this) {
}
```
package com.xiancheng.suo;
class Ticket implements Runnable{ //售票
private int tick = 200; //票
@Override
public void run() {
while (true) {
test();
if(tick <= 0){
break;
}
}
}
public synchronized void test(){
if (tick > 0) {
System.out.println(Thread.currentThread().getName() +
"卖出了第" + tick + "票");
tick--;
} else {
System.out.println("票已经卖完了");
return;
}
}
}
public class Demo01 {
public static void main(String[] args) {
Ticket ticket = new Ticket();
new Thread(ticket , "窗口1").start();
new Thread(ticket , "窗口2").start();
}
}
```