概念
程序
进程
线程
单线程与多线程
并发与并行
线程基本使用
基成Tread类
关系图
/*
@author:我与java相爱相杀---c语言梦开始的地方
今天又是努力学习的一天!!!!
*/public class Main {
public static void main(String[] args) throws InterruptedException {
Cand cand = new Cand();
cand.start();
int i=0;
while (true){
System.out.println("主线程启动"+Thread.currentThread().getName());
i++;
Thread.sleep(1000);
if (i==6)
break;}
}
}
class Cand extends Thread {
@Override
public void run() {
int time=0;
while (true) {
System.out.println("小猫叫");
time++;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
if (time==8)
break;
}
}
}
主线程结束了,子线程没结束那么应用程序就不会结束,除非所有的线程都结束了,应用程序才会结束,并且主线程和子线程会交替进行,不会阻塞,并且使用start方法开始线程他会主动调用run方法,之所以如此原因如下
,并且这样直接调用那么线程就只是main,并且会按照程序进行先进行调用run()方法内的内容,再进行后面的内容
start()启动线程的过程
实现接口Runnable
/*
@author:我与java相爱相杀---c语言梦开始的地方
今天又是努力学习的一天!!!!
*/public class Test01 {
public static void main(String[] args) {
Roud roud = new Roud();
//无法像继承Thread类时可以直接调用start方法启动线程
// roud.start();
Thread thread = new Thread(roud);
thread.start();
}
}
class Roud implements Runnable {
@Override
public void run() {
int i=0;
while (true) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("小狗叫了" + Thread.currentThread().getName());
i++;
if (i==10)
break;
}
}
}
使用这个方式实现调用start方法启动线程是用到了代理模式。我们可以来模拟一下
/*
@author:我与java相爱相杀---c语言梦开始的地方
今天又是努力学习的一天!!!!
*/public class Test02 {
public static void main(String[] args) {
Roud_ roud_ = new Roud_();
PoxyTread poxyTread = new PoxyTread(roud_);
poxyTread.start();
}
}
class PoxyTread implements Runnable{
private Runnable runnable=null;
public PoxyTread(Runnable runnable) {
this.runnable = runnable;
}
@Override
public void run() {
if (runnable!=null)
runnable.run();
}
public void start()
{
start0();
}
public void start0()
{
run();
}
}
class Roud_ implements Runnable {
@Override
public void run() {
int i = 0;
while (true) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("小狗叫了" + Thread.currentThread().getName());
i++;
if (i == 10)
break;
}
}
}
多线程执行
/*
@author:我与java相爱相杀---c语言梦开始的地方
今天又是努力学习的一天!!!!
*/public class Test03 {
public static void main(String[] args) {
T1 t1 = new T1();
T2 t2 = new T2();
Thread thread = new Thread(t1);
Thread thread1 = new Thread(t2);
thread.start();
thread1.start();
}
}
class T1 implements Runnable{
@Override
public void run() {
int i=0;
while (true)
{
System.out.println("mimi"+Thread.currentThread().getName());
i++;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
if (i==10)
break;
}
}
}
class T2 implements Runnable{
@Override
public void run() {
int i=0;
while (true)
{
System.out.println("mimi"+Thread.currentThread().getName());
i++;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
if (i==10)
break;
}
}
}
继承Thread与Runnable的区别
线程终止
线程常用方法
/*
@author:我与java相爱相杀---c语言梦开始的地方
今天又是努力学习的一天!!!!
*/public class test05 {
public static void main(String[] args) throws InterruptedException {
T_ t = new T_();
Thread thread = new Thread(t);
thread.start();
for(int i=0;i<5;i++)
{
Thread.sleep(1000);
System.out.println("hi"+i);
}
thread.interrupt();
}
}
class T_ implements Runnable{
@Override
public void run() {
while (true)
{
for(int i=0;i<100;i++)
{
System.out.println("吃包子"+i);
}
try {
Thread.sleep(20000);
} catch (InterruptedException e) {
System.out.println(Thread.currentThread().getName()+"被中断了");
}
}
}
}
如果没有interrupt的话,应该再输出5个hi后再到达睡眠时间sleep(20000)后又开始输出吃包子语句,
有了之后他直接干预了休眠时间,直接就会打印出被干预的话,然后立刻开始又打印吃包子
解析1:
例如当一个cpu在并发运行两个线程时,其中一个使用了yield让CPU先去出里另一个。但是如果CPU他是能同时兼顾这两个的时候,那么yield就不会使用成功
解析2:
例如当一个cpu在并发运行两个线程时,再运行一个线程时,另一个线程使用了join,那么就会先运行完另一个线程的内容,才会再运行这个
、
/*
@author:我与java相爱相杀---c语言梦开始的地方
今天又是努力学习的一天!!!!
*/public class test06 {
public static void main(String[] args) throws InterruptedException {
T_i t = new T_i();
Thread thread = new Thread(t);
thread.start();
for(int i=0;i<20;i++)
{
System.out.println("小弟吃包子"+i);
Thread.sleep(1000);
if (i==5)
thread.join();
}
}
}
class T_i implements Runnable{
@Override
public void run() {
int i=0;
while (true)
{
System.out.println("老大吃包子"+(++i));
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
if (i==20)
break;
}
}
}
/*
@author:我与java相爱相杀---c语言梦开始的地方
今天又是努力学习的一天!!!!
1.主线程每隔1s,输出hi,一共10次
2. 当输出到hi 5时,启动一个子线程(要求
实现Runnable),每隔1s输出hello,等
该线程输出10次 hello后,退出
3.主线程继续输出hi,直到主线程退出.
4.如图,完成代码
*/public class Test07 {
public static void main(String[] args) throws InterruptedException {
T_O t_o = new T_O();
Thread thread = new Thread(t_o);
// thread.start();
for(int i=0;i<10;i++)
{
System.out.println("hi"+i);
Thread.sleep(1000);
if (i==4) {
thread.start();
thread.join();
}
}
}
}
class T_O implements Runnable{
@Override
public void run() {
int i=0;
while (true)
{
System.out.println("hello"+(++i));
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
if (i==10)
break;
}
}
}
用户线程和守护线程
线程的生命周期
7大状态
查看状态方式
线程同步
Synchronized
/*
@author:我与java相爱相杀---c语言梦开始的地方
今天又是努力学习的一天!!!!
*/public class Test04 {
public static void main(String[] args) {
sell01 sell01 = new sell01();
Thread thread = new Thread(sell01);
Thread thread1 = new Thread(sell01);
Thread thread2 = new Thread(sell01);
thread.start();
thread1.start();
thread2.start();
}
}
class sell01 implements Runnable{
static int tick=100;
boolean loop=true;
public synchronized void sell(){
if (tick<=0)
{
System.out.println("票已卖完");
loop=false;
return;
}
try {
Thread.sleep(10);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("出售票"+Thread.currentThread().getName()+"剩余"+(--tick));
}
@Override
public void run() {
while (loop)
{
sell();
}
}
}
使用完美解决之前卖票不够了还卖的境界
锁在对象上,随机一个线程去拿这个锁打开进入操作相应的操作,然后出来再关闭,然后又随机一个来拿这个锁重复之前的步骤
互斥锁
是因为使用时会都堵塞在这,谁拿到锁谁才能进入执行操作,所以效率低了
注意事项
如果是这样就锁不住了。因为在创建时,都是new了个新对象,那么this指的对象每次都不一样
除了用this也可以用其他对象,只要是三个线程同一的对象就行,比如图上的Object,他是创建在该类的属性,所以三个线程对应的是同一个object对象
死锁
结果就是卡住了死锁
释放锁
import java.util.Scanner;
/*
@author:我与java相爱相杀---c语言梦开始的地方
今天又是努力学习的一天!!!!
*/public class test08 {
public static void main(String[] args) {
C c = new C();
new Thread(c).start();
B b = new B(c);
new Thread(b).start();
}
}
class C implements Runnable{
static boolean loop=true;
public static void setLoop(boolean loop) {
C.loop = loop;
}
@Override
public void run() {
while (loop){
System.out.println((int)(Math.random()*100+1));
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
class B implements Runnable{
C a;//想要控制C就得有C对象
public B(C a) {
this.a = a;
}
Scanner scanner=new Scanner(System.in);
@Override
public void run() {
while (true)
{
System.out.println("请输入你的字母");
char c=scanner.next().toUpperCase().charAt(0);
System.out.println(c);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
if (c=='G')
{ a.setLoop(false);//改变C控制循环的变量
break;
}
}
}
}
/*
@author:我与java相爱相杀---c语言梦开始的地方
今天又是努力学习的一天!!!!
)有2个用户分别从同一个卡上取钱(总额:10000)
2)每次都取1000,当余额不足时,就不能取款了
3)不能出现超取现象=》线程同步问题.
*/public class Test09 {
public static void main(String[] args) {
new Car().run();
new Car().run();
}
}
class Car extends Thread{
static int cash=10000;
public synchronized void m()
{
while (cash!=0)
{
cash-=1000;
System.out.println("还剩"+cash);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
@Override
public void run() {
m();
}
}