线程的基础内容
程序、进程、线程
- 一个进程中至少有一个线程
各个应用程序之间去抢占CPU资源,在同一个时间点上,CPU只能处理一个程序,看上去像是同时在进行,其实是CPU在快速的切换,进程抢占到CPU资源后,各个线程就去抢,那个线程先抢到就执行那个线程,(所以每一次执行的顺序都不一样) - 在java虚拟机上启动的时候会有一个进程java.exe,该进程中至少有一个线程,在负责java程序的执行。而且这个线程运行的代码在main方法中,该线程为主线程
- 但是线程结束,进程未必结束,但进程结束,线程一定结束,线程是进程中的一部分
线程的创建和启动
- 在java中负责线程的这个功能的是java.lang.Thread这个类
- 可以通过new Thread(创建Thread的实例)来创建新的线程
- 每个都是通过某个特定Thread对象所对应的run()方法完成其操作,run()方法称为线程体。
- 可以通过调用Thread类的start()方法来启动一个线程。
- 继承Thread类 ,重写run方法,创建对象,调用start()方法,启动线程。
代码如下:
public class A extends Thread{
@Override
public void run() {
System.out.println("我是A");
}
public static void main(String[] args) {
A a=new A();
Thread t=new Thread(a);
a.start();
}
}
-
- 创建线程的第二个方式:
- 实现Runnable接口,重写run方法,创建对象,启动线程。
代码如下:
public class B implements Runnable{
@Override
public void run() {
System.out.println("我是B");
}
public static void main(String[] args) {
B b=new B();
Thread t=new Thread(b);
//也可以这样 Thread t=new Thread(new B());
t.start();
}
}
- 以上都是单线程,下面一个多线程的应用:
卖票
public class ThreadDemo6 implements Runnable{
int Ticket=5;
@Override
public void run() {
for(int i=0;i<100;i++){
if(Ticket>0){
System.out.println(Thread.currentThread().getName()+"正在出售"+(Ticket--)+"车票");
}
}
}
public static void main(String[] args) {
ThreadDemo6 t = new ThreadDemo6();
Thread t1=new Thread(t);
Thread t2=new Thread(t);
Thread t3=new Thread(t);
Thread t4=new Thread(t);
t1.start();
t2.start();
t4.start();
t3.start();
}
}
有可能出现这样的现象:
5张车票,出售了6张
Thread-0正在出售5车票
Thread-2正在出售2车票
Thread-2正在出售1车票
Thread-3正在出售3车票
Thread-1正在出售4车票
Thread-0正在出售0车票
这样就用到了线程的同步
线程同步
- 用到了:synchronized,这个可以是同步代码块,同步对象。
线程同步的实现
public class ThreadDemo15 implements Runnable{
int sum=5;
@Override
public synchronized void run() {
for (int i = 0; i < 200; i++) {
if(sum>0){
System.out.println(Thread.currentThread().getName()+"出售"+sum--+"票");
try {
Thread.sleep(100);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) {
ThreadDemo15 t = new ThreadDemo15();
Thread t0 = new Thread(t);
Thread t1 = new Thread(t);
Thread t2 = new Thread(t);
Thread t3 = new Thread(t);
t0.start();
t1.start();
t2.start();
t3.start();
}
}
- 死锁
- 同步可以保证资源共享操作的正确性,但是过多同步也会产生死锁, 死锁一般情况下表示互相等待,是程序运行时出现的一种问题。
- 例如:
想要画的张山跟想要书李四说:“把你的画给我,我把我的书给你”,李四也说:“把书给我,我把画给你”。然后俩个人互相等待
线程间通信
–
线程间通信的实现
public class communication01 {
public static void main(String[] args){
final besiness b=new besiness();
new Thread(new Runnable() {
@Override
public void run() {
for(int i=1;i<=50;i++){
b.sub(i);
}
}
}).start();
for (int i = 1; i <= 50; i++) {
b.main(i);
}
}
}
class besiness{
private static boolean flag=true;//flag为true时允许main访问,为false时允许suB访问
public synchronized void main(int i){
while(!flag){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
for (int j = 1; j <= 10; j++) {
System.out.println("main thread==" + j + ",loop of " + i);
}
flag=false;
this.notify();
}
public synchronized void sub(int i){
while (flag){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
for (int j = 1; j <= 10; j++) {
System.out.println("sub thread==" + j + ",loop of " + i);
}
flag=true;
this.notify();
}
}