1.jvm与多线程
jvm里分为方法区、虚拟机栈、本地方法栈、堆、程序计数器
每个进程在方法区与堆里有一份
每个线程在虚拟机栈与程序计数器里有一份
2.java程序中自带的线程
一个java.exe程序中,至少存在三个线程:主线程、垃圾回收线程、异常处理线程
3.创建线程方式一:继承Thread类
/**
* @author ym
* @create 2022-01-24 17:38
* @description 测试创建线程的方法,即继承thread类 得到100以内的所有偶数
*/
public class ThreadTest extends Thread {
@Override
public void run() {
for (int i = 0; i < 1001; i++) {
if (i % 2 == 0) {
System.out.println(i);
}
}
}
}
/**
* @author ym
* @create 2022-01-24 17:40
* @description
*/
public class ThreadTest1 {
public static void main(String[] args) {
ThreadTest threadTest = new ThreadTest();
threadTest.start();
for (int i = 0; i < 1001; i++) {
if (i % 2 == 0) {
System.out.println("main");
}
}
}
}
注意:
1.不能用直接调用run方法的方式开启线程,这样的话只是相当于普通的函数调用,并没有打开新的线程
2.不能再调用一个start()过了的线程对象的start()方法
4.线程中常用方法
/**
* @author ym
* @create 2022-01-24 17:40
* @description
*/
public class ThreadTest1 {
/**
* 线程中常用方法:
* 1.start():启动当前线程,调用当前线程的run()方法
* 2.run():重写Thread类中的此方法,将创建的线程要执行的内容声明在此处
* 3.currentThread():静态方法,返回执行当前代码的线程
* 4.getName():获取当前线程的名字
* 5.setName():设置当前线程的名字
* 6.yield():释放当前cpu的执行权
* 7.join():在a线程中调用b线程的join()方法,则a线程会一直阻塞到b线程完全执行结束
* 8.stop():已过时,当执行此方法时,强制结束当前线程
* 9.sleep(long milltime):休眠,休眠期间当前线程是阻塞状态
* 10.isAlive():判断当前线程是否存活
*
* @param args
*/
public static void main(String[] args) throws InterruptedException {
ThreadTest threadTest = new ThreadTest();
// 5.setName():设置当前线程的名字
Thread.currentThread().setName("主线程ym");
//1.start():启动当前线程,调用当前线程的run()方法
threadTest.start();
for (int i = 0; i < 1001; i++) {
if (i % 2 == 0) {
// 3.currentThread():静态方法,返回执行当前代码的线程
//4.getName():获取当前线程的名字
System.out.println(Thread.currentThread().getName() + "main\t" + i);
}
if (i == 800) {
// 7.join():在a线程中调用b线程的join()方法,则a线程会一直阻塞到b线程完全执行结束
threadTest.join();
}
if (i == 900) {
// 8.stop():已过时,当执行此方法时,强制结束当前线程
Thread.currentThread().stop();
}
}
}
}
/**
* @author ym
* @create 2022-01-24 17:38
* @description 测试创建线程的方法,即继承thread类 得到100以内的所有偶数
*/
public class ThreadTest extends Thread {
//2.run():重写Thread类中的此方法,将创建的线程要执行的内容声明在此处
@Override
public void run() {
// 5.setName():设置当前线程的名字
setName("测试线程ym");
for (int i = 0; i < 1001; i++) {
if (i % 2 == 0) {
//3.currentThread():静态方法,返回执行当前代码的线程
//4.getName():获取当前线程的名字
System.out.println(currentThread().getName() + i);
}
if (i == 700) {
try {
// 9.sleep(long milltime):休眠,休眠期间当前线程是阻塞状态
sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if (i == 850) {
// 10.isAlive():判断当前线程是否存活
System.out.println(isAlive());
}
if (i % 10 == 0) {
// 6.yield():释放当前cpu的执行权
yield();
}
}
}
}
5.创建线程的第二个方法:实现runnable接口
/**
* @author ym
* @create 2022-01-24 20:36
* @description 第二种创建线程的方式,实现runnable接口
*/
public class ThreadTest2 {
public static void main(String[] args) {
MyThread myThread = new MyThread();
Thread thread = new Thread(myThread);
thread.start();
Thread thread1 = new Thread(myThread);
thread1.start();
}
}
class MyThread implements Runnable {
/**
* When an object implementing interface <code>Runnable</code> is used
* to create a thread, starting the thread causes the object's
* <code>run</code> method to be called in that separately executing
* thread.
* <p>
* The general contract of the method <code>run</code> is that it may
* take any action whatsoever.
*
* @see Thread#run()
*/
@Override
public void run() {
for (int i = 0; i < 100; i++) {
if (i % 2 == 0) {
System.out.println(i + "\t" + Thread.currentThread().getName());
}
}
}
}
6.常见多线程初识问题:窗口卖票问题
需求:3个窗口共卖出100张票
实现方案1:用继承thread的方式,不过此时需注意,票数需要static
package com.exer;
/**
* @author ym
* @create 2022-01-24 20:12
* @description 三个窗口卖票问题
*/
public class TicketDemo {
public static int tickets = 100;
public static void main(String[] args) {
TicketSell ticketSell1 = new TicketSell();
TicketSell ticketSell2 = new TicketSell();
TicketSell ticketSell3 = new TicketSell();
ticketSell1.start();
ticketSell2.start();
ticketSell3.start();
}
}
class TicketSell extends Thread{
@Override
public void run() {
while (true){
if (TicketDemo.tickets>0){
TicketDemo.tickets--;
System.out.println(TicketDemo.tickets+"\t"+getName());
}else {
break;
}
}
}
}
**实现方案2:用实现runnable接口的方式,此时便不需将票数static了,因为每个线程都共用一个实现了runnable的线程操作对象 **
package com.exer;
/**
* @author ym
* @create 2022-01-24 20:45
* @description
*/
public class TicketDemo1 {
public static void main(String[] args) {
MyThread myThread = new MyThread();
Thread thread1 = new Thread(myThread);
Thread thread2 = new Thread(myThread);
Thread thread3 = new Thread(myThread);
thread1.start();
thread2.start();
thread3.start();
}
}
class MyThread implements Runnable {
public int tickets = 100;
/**
* When an object implementing interface <code>Runnable</code> is used
* to create a thread, starting the thread causes the object's
* <code>run</code> method to be called in that separately executing
* thread.
* <p>
* The general contract of the method <code>run</code> is that it may
* take any action whatsoever.
*
* @see Thread#run()
*/
@Override
public void run() {
while (true) {
if (tickets > 0) {
tickets--;
System.out.println(Thread.currentThread().getName() + "\t" + tickets);
} else {
break;
}
}
}
}
7.总结:在开发中,多线程创建尽量使用实现runnable()接口的方法,原因:
1.实现的方式没有类的单继承性的局限
2。实现的方式更适合来处理多个线程有共享数据的情况