今天把Java多线程学习了一下,作如下总结
进程与线程进程是程序关于某个数据集合的一次执行过程
线程是操作系统能够运算调度的最小单位,是进程中单一顺序的控制流
一个进程可以并发执行多个线程,进程是线程的容器
例如:电脑QQ,QQ是进程,发送消息,QQ空间就是线程
单线程单线程,就是程序执行时,进程中的线程顺序是连续的
package ThreadExample;
public class Singal_ThreadExample {
//单线程演示
//单线程,程序执行时,进程中的线程顺序是连续的
public static void main(String[] args) {
MyThread m1 = new MyThread("MyThread1");
MyThread m2 = new MyThread("MyTHread2");
m1.run();
m2.run();
//单线程的限制
//m2调用run()方法,要等m1调用完了之后才可以继续调用
//多线程可以实现上述结果交叉输出 多线程即进程可以并发执行
//实际上所有的多线程代码执行顺序都是不确定的,每次执行的结果都是随机的。
}
}
//单线程
class MyThread {
String str;
public MyThread(String str) {
this.str = str;
}
void run() {
for (int i = 0; i < 3; i++) {
System.out.println("输入参数是: " + str);
}
}
}
多线程
多线程可以使单个程序内部在同一时刻执行多个代码段,完成不同的任务。一个复杂的任务可以分解为多个子任务交予线程执行,实现异步执行环境
多线程可以实现上述结果交叉输出 多线程即进程可以并发执行
例如,浏览器就是一个多线程的例子,可以浏览网页时同时播放声音和动画
常用的两个,一是创建线程子类,继承Thread类;二是在定义的类中实现Runnable接口
创建Thread类的子类创建一个类,继承Thread类并且重写其中的run()方法
package ThreadExample;
public class MyThreadExample {
//创建Thread类的子类来实现多线程
static class Thread1 extends Thread {
private String str = null;
public Thread1(String str) {
this.str = str;
}
//重写Thread中的run()方法
public void run() {
for (int i = 0; i < 3; i++) {
System.out.println("你输入的是:" + str);
try {
//sleep(long millis): 在指定的毫秒数内让当前正在执行的线程休眠(暂停执行)
//Thread.sleep()方法调用目的是不让当前线程独自霸占该进程所获取的CPU资源,以留出一定时间给其他线程执行的机会。
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) {
Thread1 t1 = new Thread1("Thread1");
Thread1 t2 = new Thread1("===============");
Thread1 t3 = new Thread1("Thread2");
t1.start();
t2.start();
t3.start();
}
}
实现Runnable接口
Java不支持多线程,如果要继承Thread后就无法继承其他类,但是可以实现Runnable接口并且重写run()方法实现多线程
package ThreadExample;
public class RunnableExample {
//实现Runnable
static class Mythread implements Runnable {
private String str;
public Mythread(String str) {
this.str = str;
}
//重写run()方法
@Override
public void run() {
for (int i = 0; i < 3; i++) {
System.out.println("你输入的是:" + str);
try {
//Thread.sleep()方法调用目的是不让当前线程独自霸占该进程所获取的CPU资源,以留出一定时间给其他线程执行的机会。
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) {
Mythread t1 = new Mythread("MyThread1");
Mythread t2 = new Mythread("MyThread2");
Mythread t3 = new Mythread("============");
//将目标对象传递给Thread实例
Thread thread1 = new Thread(t1);
Thread thread2 = new Thread(t2);
Thread thread3 = new Thread(t3);
thread1.start();
thread2.start();
thread3.start();
}
}
实现多线程分别打印0~99的数字的功能
实现多线程分别打印0~99的数字的功能
package ThreadExample.Practice;
public class Practice1 {
static class MyThread extends Thread {
private int num;
public MyThread(int num) {
this.num = num;
}
//重写Thread中的run()方法
public void run() {
//for (int i = 0; i < 100; i++) {
System.out.println("num: " + num);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// }
}
}
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
MyThread t1 = new MyThread(i);
t1.start();
}
}
}
Runnable接口和Thread类的区别
两种方法都要执行start()方法来为线程分配系统资源,调度线程并且执行线程run()方法
当一个线程已经继承另一个类时,就应该使用Runnable接口来实现多线程
如果一个程序激活了多个线程,并且多个线程共享同一资源,可能会发生冲突。这个时候就要使用进程的同步机制来解决
线程同步指的是通过特定的同步机制来控制多线程间的执行顺序,即使多个线程按照预定的先后次序执行
synchronized 关键字可以修饰方法或者代码块,相当于给修饰的方法或者代码块上锁,有效防止资源冲突
package ThreadExample;
public class SameThread {
//线程同步问题
public static int count = 10;
//synchronized 关键字可以修饰方法或者代码块,相当于给修饰的方法或者代码块上锁,有效防止资源冲突
public static synchronized int buyTicket() {
if (count <= 0) {
return -1; //无票
}
count--;
System.out.println("剩余票数: " + count);
return count;
}
public static void main(String[] args) {
for (int i = 0; i < 15; i++) {
new Thread() {
public void run() {
SameThread.buyTicket();
}
}.start();
}
}
}
同步锁的例题
三个窗口同时售卖20张票
多线程同步锁的应用 三个窗口同时售卖20张票
package ThreadExample.PracticeExample;
public class Example1 {
//多线程同步锁的应用 三个窗口同时售卖20张票
static class Sation extends Thread {
public Sation(String name) {
super(name);
}
static int count = 20; //票数
static Object object = "aa"; //创建一个同步锁 静态的钥匙
//重写run方法
public void run() {
while (count > 0) {
//使用一个锁, // 进去的人会把钥匙拿在手上,出来后才把钥匙拿让出来
synchronized (object) {
if (count > 0) {
System.out.println(getName() + "卖出了第 " + count + "张票!");
count--;
} else {
System.out.println("票卖完了!");
}
}
try {
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) {
Sation s1 = new Sation("站台1");
Sation s2 = new Sation("站台2");
Sation s3 = new Sation("站台3");
s1.start();
s2.start();
s3.start();
}
}
银行取钱1
两个人AB通过一个账户A在柜台取钱和B在ATM机取钱!
package ThreadExample.PracticeExample;
import java.util.Objects;
public class Example2 {
//两个人AB通过一个账户A在柜台取钱和B在ATM机取钱!
public static void main(String[] args) {
Bank bank = new Bank();
PersonA personA = new PersonA(bank, "ATM", "小明");
PersonB personB = new PersonB(bank, "Counter", "小白");
personA.start();
personB.start();
}
}
//银行类
class Bank {
//账户的金额为1000
static double money = 1000;
//在柜台取钱
public void Counter(double money) {
this.money -= money;
System.out.println("柜台取钱 " + money + "还剩 " + this.money);
}
//在ATM机取钱
public void ATM(double money) {
this.money -= money;
System.out.println("ATM取钱 " + money + "还剩 " + this.money);
}
//提供一个对外取款的途径
public synchronized void OutMoney(double money, String mode) throws Exception {
if (money > this.money) {
//检验余额是否充足
throw new Exception("取款金额" + money + ",余额只剩" + this.money + ",取款失败!");
}
if (Objects.equals(mode, "ATM")) {
ATM(money);
} else {
Counter(money);
}
}
}
//创建一个人类,模拟取钱 继承自Thread类
class PersonA extends Thread {
//哪个银行
private Bank bank;
//何种方式
private String mode;
//姓名
private String name;
public PersonA(Bank bank, String mode, String name) {
this.bank = bank;
this.mode = mode;
this.name = name;
}
@Override
public void run() {
while (bank.money >= 100) {
try {
bank.OutMoney(100, mode);
} catch (Exception e) {
e.printStackTrace();
}
try {
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class PersonB extends Thread {
//哪个银行
private Bank bank;
//何种方式
private String mode;
//姓名
private String name;
public PersonB(Bank bank, String mode, String name) {
this.bank = bank;
this.mode = mode;
this.name = name;
}
@Override
public void run() {
while (bank.money >= 200) {
try {
bank.OutMoney(200, mode);
} catch (Exception e) {
e.printStackTrace();
}
try {
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
银行取钱2
编写一个模拟银行存款的程序。假设有两个储户都去银行往同一账户存款,一次存100,每次存3次。要求储户每存一次前,账户余额增加100,并在控制台输出当前账户的余额。
package ThreadExample.Practice;
public class Practice2 {
public static void main(String[] args) {
//进程同步锁的使用
Bank bank = new Bank();
Person a = new Person(bank);
Person b = new Person(bank);
Person c = new Person(bank);
Thread t1 = new Thread(a);
Thread t2 = new Thread(b);
Thread t3 = new Thread(c);
t1.start();
t2.start();
t3.start();
}
}
//银行类
class Bank {
//账户的初始金额为1000
static double money = 1000;
//存钱的方法
public void SaveMoney(double getMoney) {
money += getMoney;
System.out.println("柜台存钱 " + getMoney + ",总金额为 " + money);
}
}
//创建一个存钱的人类,模拟存钱
class Person implements Runnable {
Bank bank;
static Object object = "aa"; //创建一个同步锁
public Person(Bank bank) {
this.bank = bank;
}
//重写run()方法
@Override
public void run() {
//存到3000块停止存钱
while (bank.money < 3000) {
//同步锁 金额随存钱次数的增加而不同步改变
synchronized (object) {
try {
bank.SaveMoney(100);
} catch (Exception e) {
e.printStackTrace();
}
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
欢迎大家指正,over
作者:爱吃水果的cc



