1.进程与线程
2.创建线程的三种方法
3.线程的5种状态与生命周期
4.sleep()方法
5.join()方法
6.线程优先级
7.线程同步问题及解决
8.线程间的通信问题
进程:计算机同时使用多个软件时不会发生冲突就是进程的作用
线程:比进程更小的运行单位,一个进程包含多个线程
线程将cpu分成多个单位小块,随机决定一个小块执行哪一个任务,由于每个小块的单位很小,人会以为它在同时执行几个任务
package com.hala.thread;
//一个文件只允许有一个public 类
class MyThread extends Thread{
public void run(){
System.out.println(getName()+"线程正在执行!");
}
}
public class ThreadTest {
//该程序有两个线程,一个是主函数的主线程,一个是mt线程
public static void main(String[] args) {
System.out.println("主线程1");
MyThread mt=new MyThread();
//启动线程,该方法只能有一个,即线程只能被启动一次
mt.start();
System.out.println("主线程2");
}
}
输出结果
主线程1
主线程2
Thread-0线程正在执行!
⚠️简便输出System.out语句的方法 输入 sysout 点alt+/。
package com.hala.thread;
class MyThread extends Thread{
public MyThread(String name){
super(name);
}
public void run(){
for(int i=0;i<3;i++){
System.out.println(getName()+"正在执行!"+i);
}
}
}
public class ThreadTest {
public static void main(String[] args) {
System.out.println("主线程1");
MyThread mt1=new MyThread("线程1");
MyThread mt2=new MyThread("线程2");
mt1.start();
mt2.start();
}
}
输出结果
主线程1
线程1正在执行!0
线程1正在执行!1
线程2正在执行!0
线程2正在执行!1
线程2正在执行!2
线程1正在执行!2
⚠️这里哪个线程先运行是随机的
package com.hala.runnable;
class PrintRunnable implements Runnable{
public void run(){
for(int i=0;i<3;i++){
//此处调用name的方法与上边是不同的
System.out.println(Thread.currentThread().getName()+"正在执行"+i);
}
}
}
public class ThreadTest {
public static void main(String[] args) {
System.out.println("主线程1");
PrintRunnable pr=new PrintRunnable();
Thread t1=new Thread(pr);
t1.start();
Thread t2=new Thread(pr);
t2.start();
}
}
输出结果
主线程1
Thread-0正在执行0
Thread-0正在执行1
Thread-0正在执行2
Thread-1正在执行0
Thread-1正在执行1
Thread-1正在执行2
package com.hala.runnable;
class PrintRunnable implements Runnable{
//此处两个线程共享了资源i
int i=0;
public void run(){
for( ;i<3;i++){
//此处调用name的方法与上边是不同的
System.out.println(Thread.currentThread().getName()+"正在执行"+i);
}
}
}
public class ThreadTest {
public static void main(String[] args) {
System.out.println("主线程1");
PrintRunnable pr=new PrintRunnable();
Thread t1=new Thread(pr);
t1.start();
Thread t2=new Thread(pr);
t2.start();
}
}
输出结果
主线程1
Thread-0正在执行0
Thread-1正在执行0
Thread-0正在执行1
Thread-1正在执行2
package com.hala.runnable;
class MyThread extends Thread{
public void run(){
for(int i=1;i<=3;i++){
System.out.println(getName()+"正在执行"+i);
try {
//使得线程休眠1s,但因为其接下来进入可执行状态,所以实际时间大于1s
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class ThreadTest {
public static void main(String[] args) {
System.out.println("主线程1");
MyThread mt1=new MyThread();
MyThread mt2=new MyThread();
mt1.start();
mt2.start();
}
}
输出结果
主线程1
Thread-1正在执行1
Thread-0正在执行1
Thread-1正在执行2
Thread-0正在执行2
Thread-1正在执行3
Thread-0正在执行3
package com.hala.runnable;
class MyThread extends Thread{
public void run(){
for(int i=1;i<=3;i++){
System.out.println(getName()+"正在执行"+i);
}
}
}
public class ThreadTest {
public static void main(String[] args) {
MyThread mt1=new MyThread();
MyThread mt2=new MyThread();
mt1.start();
try {
//mt1优先执行
mt1.join();
//mt1优先执行2毫秒
//mt1.join(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
mt2.start();
}
}
输出结果
Thread-0正在执行1
Thread-0正在执行2
Thread-0正在执行3
Thread-1正在执行1
Thread-1正在执行2
Thread-1正在执行3
package com.hala.runnable;
class MyThread extends Thread{
public MyThread(String name){
super(name);
}
public void run(){
for(int i=1;i<=3;i++){
System.out.println(getName()+"正在执行"+i);
}
}
}
public class ThreadTest {
public static void main(String[] args) {
//获取主线程的优先级
int mainPriority=Thread.currentThread().getPriority();
System.out.println("主线程的优先级为:"+mainPriority);
MyThread mt1=new MyThread("线程1");
//mt1.setPriority(10);
mt1.setPriority(Thread.MAX_PRIORITY);
mt1.start();
System.out.println("线程1的优先级为:"+mt1.getPriority());
//注意并不是优先级越高就一定先执行,这与操作系统有关
}
}
输出结果
主线程的优先级为:5
线程1的优先级为:10
线程1正在执行1
线程1正在执行2
线程1正在执行3
Bank类
package bank;
public class Bank {
private String account;
private int balance;
public Bank(String account,int balance) {
setAccount(account);
setBalance(balance);
}
public String getAccount() {
return account;
}
public void setAccount(String account) {
this.account = account;
}
public int getBalance() {
return balance;
}
public void setBalance(int balance) {
this.balance = balance;
}
@Override
public String toString() {
return "Bank [账号:" + account + ", 余额:" + balance + "]";
}
/**
* 存款操作 每次存100
*/
public void saveAccount(){
int balance=getBalance();
//这里得休眠操作模拟的是多个线程同步进行时该线程进行到一部分时被打断的情况
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
balance+=100;
setBalance(balance);
System.out.println("存款后的账户余额为:"+balance);
}
/**
* 取款操作 每次取20
*/
public void drawAccount(){
int balance=getBalance();
balance-=20;
//这里得休眠操作模拟的是多个线程同步进行时该线程进行到一部分时被打断的情况
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
setBalance(balance);
System.out.println("取款后的账户余额为:"+balance);
}
}
SaveAccount 类
package bank;
//存款线程操作
public class SaveAccount implements Runnable {
Bank bank;
public SaveAccount(Bank bank) {
this.bank=bank;
}
@Override
public void run() {
// TODO Auto-generated method stub
bank.saveAccount();
}
}
DrawAccount类
package bank;
//取款线程操作
public class DrawAccount implements Runnable {
Bank bank;
public DrawAccount(Bank bank){
this.bank=bank;
}
@Override
public void run() {
bank.drawAccount();
}
}
BankTest类
package bank;
public class BankTest {
public static void main(String[] args) {
Bank bank=new Bank("1001",1000);
SaveAccount sa=new SaveAccount(bank);
DrawAccount da=new DrawAccount(bank);
Thread save=new Thread(sa);
Thread draw=new Thread(da);
save.start();
draw.start();
//由于线程被打断,所以取款操作最初得到的余额其实还是1000
//最终导致了银行账户的错误
try {
save.join();
draw.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(bank);
}
}
输出结果
存款后的账户余额为:1100
取款后的账户余额为:980
Bank [账号:1001, 余额:980]
package bank;
public class Bank {
private String account;
private int balance;
public Bank(String account,int balance) {
setAccount(account);
setBalance(balance);
}
public String getAccount() {
return account;
}
public void setAccount(String account) {
this.account = account;
}
public int getBalance() {
return balance;
}
public void setBalance(int balance) {
this.balance = balance;
}
@Override
public String toString() {
return "Bank [账号:" + account + ", 余额:" + balance + "]";
}
/**
* 存款操作
*/
//synchronized表示这个方法进行完之前不进行其他方法
public synchronized void saveAccount(){
int balance=getBalance();
//这里得休眠操作模拟的是多个线程同步进行时该线程进行到一部分时被打断的情况
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
balance+=100;
setBalance(balance);
System.out.println("存款后的账户余额为:"+balance);
}
/**
* 取款操作
*/
public void drawAccount() {
synchronized (this) {
int balance = getBalance();
balance -= 20;
// 这里得休眠操作模拟的是多个线程同步进行时该线程进行到一部分时被打断的情况
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
setBalance(balance);
System.out.println("取款后的账户余额为:" + balance);
}
}
}
输出结果
存款后的账户余额为:1100
取款后的账户余额为:1080
Bank [账号:1001, 余额:1080]
线程间的通信问题针对的是银行取款不能多余余额的问题,这是会涉及到通信的问题
Queue类
package com.hala.queue;
public class Queue {
private int n;
boolean flag=false;
//flag的作用是确定何时生产何时消费
public synchronized int getN() {
if(!flag){
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println("消费:"+n);
flag=false;
//如果没有唤醒会发生死锁的现象,即两个方法都处于等待状态
notifyAll();
return n;
}
public synchronized void setN(int n) {
if(flag){
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println("生产:"+n);
this.n = n;
flag=true;
notifyAll();
}
}
Produce类
package com.hala.queue;
public class Produce implements Runnable {
Queue queue;
public Produce(Queue queue){
this.queue=queue;
}
@Override
public void run() {
int i=0;
while(true){
queue.setN(i++);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
Consumer类
package com.hala.queue;
public class Consumer implements Runnable {
Queue queue;
public Consumer(Queue queue){
this.queue=queue;
}
@Override
public void run() {
while(true){
queue.getN();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
Test类
package com.hala.queue;
public class Test {
public static void main(String[] args) {
Queue queue=new Queue();
new Thread(new Produce(queue)).start();
new Thread(new Consumer(queue)).start();
}
}
输出结果
生产:0
消费:0
生产:1
消费:1
生产:2
消费:2
生产:3
消费:3
生产:4
消费:4
生产:5
消费:5
生产:6
消费:6
生产:7
消费:7
生产:8
消费:8
生产:9
消费:9
生产:10
消费:10
生产:11
消费:11
生产:12
消费:12
生产:13
消费:13
生产:14
消费:14
生产:15
消费:15
生产:16
消费:16