文章目录 线程组成 线程特点 创建线程 创建线程(一) 第一种方式: 获取和修改线程名称 卖票案例 创建线程(二
文章目录
- 线程组成
- 线程特点
- 创建线程
- 创建线程(一)
- 第一种方式:
- 获取和修改线程名称
- 卖票案例
- 创建线程(二)
- 第二种方式:
- 补充使用匿名内部类:
- Runnable案例1:
- Runnable案例2:
线程组成
任何一个线程都具有基本的组成部分:
- 堆空间:存储线程需使用的对象,多个线程可以共享堆中的对象。
- 栈空间:存储线程需使用的局部变量,每个线程都拥有独立的栈。
线程特点
- 效率高
- 可防止单一线程长时间独占CPU
创建线程
创建线程三种方式:
创建线程(一)
第一种方式:
创建线程的代码:
package com.wlw.thread;/**
* 线程类
* 创建线程的第一种方式
*/
public class MyThread extends Thread{ //第一步,继承Thread类,
@Override
public void run() { //第二步,重写run()方法,在run()方法内编写功能代码
for (int i = 0; i < 2000; i++) {
System.out.println("子线程-------------"+i);
}
}
}package com.wlw.thread;
public class TestThread {
public static void main(String[] args) {
//第三步,创建线程对象(new)
MyThread myThread = new MyThread();
//第四步,调用start()方法,这个方法是启动线程
myThread.start();
//主线程执行
for (int i = 0; i < 2000; i++) {
System.out.println("主线程----------------------"+i);
}
}
}
//循环次数过小,可能出现运行结果不符合理想,总是一个线程执行完,再执行另一个线程,此时就加大循环次数,应该就会出现理想结果,如下:(部分执行结果)
/*
子线程-------------241
主线程----------------------261
子线程-------------242
主线程----------------------262
子线程-------------243
主线程----------------------263
主线程----------------------264
主线程----------------------265
子线程-------------244
子线程-------------245
子线程-------------246
主线程----------------------266
子线程-------------247
子线程-------------248
子线程-------------249
*/
获取和修改线程名称
- 在Thread的子类中调用this. getId ()或this. getName () (只适合在继承了Thread的类中使用)
- 使用Thread. currentThread(). getId()和Thread. currentThread (). getName ()(在哪都能用)
- 调用线程对象的setName()方法(创建完对象,再调用setName())
- (建议使用)使用线程子类的构造方法赋值(在带参构造方法中,调用父类Thread的带参构造,super(name))
代码:
package com.wlw.thread;/**
* 线程类
* 创建线程的第一种方式
*/
public class MyThread extends Thread{ //第一步,继承Thread类,
public MyThread() {
}
public MyThread(String name){
super(name);
}
@Override
public void run() { //第二步,重写run()方法,在run()方法内编写功能代码
for (int i = 0; i < 2000; i++) {
//第一种方式:在Thread的子类中调用this. getId ()或this. getName () (只适合在继承了Thread的类中使用)
//System.out.println("线程ID:"+this.getId()+"线程名称:"+this.getName()+",子线程-------------"+i);
//第二种方式:使用Thread. currentThread() 获取当前线程
System.out.println("线程ID:"+Thread.currentThread().getId() +"线程名称:"+Thread.currentThread().getName() +",子线程-------------"+i);
}
}
}package com.wlw.thread;
public class TestThread {
public static void main(String[] args) {
//第三步,创建线程对象(new)
MyThread myThread01 = new MyThread("我的子线程1");
//修改线程名称,setName()
//thread_demo01.setName("我的子线程1");
//第四步,调用start()方法,这个方法是启动线程
myThread01.start();
MyThread myThread02 = new MyThread("我的子线程2");
//thread_demo02.setName("我的子线程2");
myThread02.start();
//主线程执行
for (int i = 0; i < 2000; i++) {
System.out.println("主线程----------------------"+i);
}
}
}
卖票案例
/***使用继承Thread类实现4个窗口各卖100张票
*/
package com.wlw.thread;
/**
* 卖票窗口类(继承类)
*/
public class TickeWin extends Thread {
public TickeWin(){
}
public TickeWin(String name){
super(name);
}
@Override
public void run() {
//买票功能
for (int i = 1; i <= 100; i++){
System.out.println("ID:"+Thread.currentThread().getId()+","+Thread.currentThread().getName()+",卖出了第"+i+"张票");
}
/* int ticket = 100;//票
while (true){
if(ticket <= 0){
break;
}
System.out.println(Thread.currentThread().getName()+",卖出了第"+ticket+"张票");
ticket--;
}*/
}
}package com.wlw.thread;
public class TestWin {
public static void main(String[] args) {
//创建四个对象
TickeWin tickeWin1 = new TickeWin("窗口1");
TickeWin tickeWin2 = new TickeWin("窗口2");
TickeWin tickeWin3 = new TickeWin("窗口3");
TickeWin tickeWin4 = new TickeWin("窗口4");
//启动线程
tickeWin1.start();
tickeWin2.start();
tickeWin3.start();
tickeWin4.start();
}
}
创建线程(二)
第二种方式:
代码:
package com.wlw.thread;/**
* 线程类
* 创建线程的第二种方式
*/
public class MyRunnable implements Runnable{ //第一步:定义一个类,实现Runnable接口
@Override
public void run() { //第二步,覆盖run()方法,在run()方法内编写功能代码
for (int i = 0; i < 2000; i++) {
System.out.println(Thread.currentThread().getName()+",子线程---------------"+i);
}
}
}package com.wlw.thread;
public class TestRunnable {
public static void main(String[] args) {
//第三步,创建实现类对象(new)
//创建MyRunnable对象,表示线程要实现的功能
MyRunnable myRunnable = new MyRunnable();
//第四步,创建线程对象,把实现类对象传递给线程对象
Thread thread = new Thread(myRunnable,"我的线程");
//第五步,调用start()方法,这个方法是启动线程
thread.start();
for (int i = 0; i < 2000; i++) {
System.out.println("主线程========================"+i);
}
}
}
补充使用匿名内部类:
代码:
package com.wlw.thread;public class TestRunnable {
public static void main(String[] args) {
/*
//第三步,创建实现类对象(new)
//创建MyRunnable对象,表示线程要实现的功能
MyRunnable myRunnable = new MyRunnable();
//第四步,创建线程对象,把实现类对象传递给线程对象
Thread thread = new Thread(myRunnable,"我的线程");
//第五步,调用start()方法,这个方法是启动线程
thread.start();
*/
//使用匿名内部类
//创建可运行对象,相当于new一个Runnable的子类
Runnable runnable = new Runnable() {
@Override
public void run() {
for (int i = 0; i < 2000; i++) {
System.out.println(Thread.currentThread().getName()+",子线程---------------"+i);
}
}
};
//创建线程
Thread thread = new Thread(runnable,"我的匿名内部类的线程");
thread.start();
for (int i = 0; i < 2000; i++) {
System.out.println("主线程========================"+i);
}
}
}
Runnable案例1:
四个窗口共卖100张票
注意:会出现多个窗口卖了同一张票,这是一个线程安全问题,后面解决(!!!!!!!!!!!)
package com.wlw.thread.caseDemo;/**
* 票类(共享资源)
*/
public class Ticket implements Runnable{
int ticket = 100; //票总共100张
//售票功能
@Override
public void run() {
while (true){
if(ticket <= 0){
break;
}
System.out.println(Thread.currentThread().getName()+"卖了第"+ticket+"张票");
ticket--;
}
}
}package com.wlw.thread.caseDemo;
public class TestTicket {
public static void main(String[] args) {
// 创建实现类对象
Ticket ticket = new Ticket();
//创建线程对象
Thread thread1 = new Thread(ticket,"窗口1");
Thread thread2 = new Thread(ticket,"窗口2");
Thread thread3 = new Thread(ticket,"窗口3");
Thread thread4 = new Thread(ticket,"窗口4");
//调用start()方法,启动线程
thread1.start();
thread2.start();
thread3.start();
thread4.start();
/*
会出现多个窗口卖了同一张票,这是一个线程安全问题,后面解决(!!!!!!!!!!!!!!!!)
*/
}
}
Runnable案例2:
注意:一开始会出现存取钱时,余额显示不准确,这是一个线程安全问题,后面解决(!!!!!!!!!!!)
package com.wlw.thread.caseDemo;/**
* 银行卡类
*/
public class BankCard {
private Double money;
public Double getMoney() {
return money;
}
public void setMoney(Double money) {
this.money = money;
}
}package com.wlw.thread.caseDemo;
/**
* 存钱
*/
public class AddMoney implements Runnable {
private BankCard bankCard;
public AddMoney(BankCard bankCard){
this.bankCard = bankCard;
}
//存钱功能
@Override
public void run() {
for (int i = 0; i < 10; i++) {
bankCard.setMoney(bankCard.getMoney() + 1000);
System.out.println(Thread.currentThread().getName()+"存了1000块钱,余额是:"+bankCard.getMoney());
}
}
}package com.wlw.thread.caseDemo;
/**
* 取钱
*/
public class SubMoney implements Runnable {
private BankCard bankCard;
public SubMoney(BankCard bankCard){
this.bankCard = bankCard;
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
if(bankCard.getMoney() >= 1000){
bankCard.setMoney(bankCard.getMoney()-1000);
System.out.println(Thread.currentThread().getName()+"取了1000块钱,余额是:"+bankCard.getMoney());
}else {
System.out.println("余额不足");
i--;
}
}
}
}package com.wlw.thread.caseDemo;
public class TestBankCard {
public static void main(String[] args) {
//1.创建银行卡
BankCard bankCard = new BankCard();
bankCard.setMoney(0.0);
//2.创建存取功能对象
AddMoney addMoney = new AddMoney(bankCard);
SubMoney subMoney = new SubMoney(bankCard);
//3.创建线程对象
Thread thread1 = new Thread(addMoney,"存钱线程");
Thread thread2 = new Thread(subMoney,"取钱线程");
//4.启动线程
thread1.start();
thread2.start();
}
}
使用匿名内部类:
package com.wlw.thread.caseDemo;public class TestBankCard2 {
public static void main(String[] args) {
//1.创建银行卡
BankCard bankCard = new BankCard();
bankCard.setMoney(0.0);
//2.存取功能
Runnable add = new Runnable() {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
bankCard.setMoney(bankCard.getMoney() + 1000);
System.out.println(Thread.currentThread().getName()+ "存了1000块钱,余额是:" +bankCard.getMoney());
}
}
};
Runnable sub = new Runnable() {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
if(bankCard.getMoney() >= 1000){
bankCard.setMoney(bankCard.getMoney() - 1000);
System.out.println(Thread.currentThread().getName()+ "取了1000块钱,余额是:" +bankCard.getMoney());
}else {
System.out.println("余额不足,请充值");
i--;
}
}
}
};
//3.创建线程对象,并启动
new Thread(add,"存钱线程").start();
new Thread(sub,"取钱线程").start();
}
}