多线程的创建一,方式一:继承于thread类
- 1.创建一个继承于Thread类的子类
- 2.重写Thread类的run()–>将此线程执行的操作声明在run()中
- 3.创建Thread类的子类的对象
- 4.通过此对象调用start():①启动当前线程 ②调用当前线程的run()
- 例子:遍历100以内的所有的偶数
public class TreadTest {
public static void main(String[] args) {
//3.创建Thread类的子类的对象
MyThread t1 = new MyThread();//主线程中造的对象
//4.通过此对象调用start()
t1.start();//调用方法后,生成新的线程,并在新的线程中执行方法
//问题一:不能直接调用run()方式启动线程
// t1.run();//仍然在主线程中进行
//问题二:再启动一个线程,遍历100以内的偶数。不可以让已经start()的线程去执行,会报IllegalThreadStateException异常。
// t1.start();
//需要重新创建一个线程的对象
MyThread t2 = new MyThread();
t2.start();
System.out.println("hello");//主线程中
for(int i = 0; i < 100; i ++){
if(i % 2 == 0){
System.out.println(Thread.currentThread().getName() + ":" + i + "********main********");
}
}
}
}
//1.创建一个继承于Thread类的子类
class MyThread extends Thread{
//2.重写Thread类的run()
@Override
public void run() {
for(int i = 0; i < 100; i ++){
if(i % 2 == 0){
System.out.println(Thread.currentThread().getName() + ":" + i);
}
}
}
}
练习:创建两个分线程,其中一个线程遍历100以内的偶数,另一个线程遍历100以内的奇数
public class ThreadDemo {
public static void main(String[] args) {
//方式一
// MyThread1 m1 = new MyThread1();
// MyThread2 m2 = new MyThread2();
//
// m1.start();
// m2.start();
//创建Thread类的匿名子类的方式
new Thread(){
@Override
public void run() {
for(int i = 0; i < 100; i ++){
if(i % 2 == 0){
System.out.println(Thread.currentThread().getName() + ":" + i);
}
}
}
}.start();
new Thread(){
@Override
public void run() {
for(int i = 0; i < 100; i ++){
if(i % 2 != 0){
System.out.println(Thread.currentThread().getName() + ":" + i);
}
}
}
}.start();
}
}
class MyThread1 extends Thread{
@Override
public void run() {
for(int i = 0; i < 100; i ++){
if(i % 2 == 0){
System.out.println(Thread.currentThread().getName() + ":" + i);
}
}
}
}
class MyThread2 extends Thread{
@Override
public void run() {
for(int i = 0; i < 100; i ++){
if(i % 2 != 0){
System.out.println(Thread.currentThread().getName() + ":" + i);
}
}
}
}
测试Thread中的常用方法:
- 1.start():启动当前线程;调用当前线程的run()
- 2.run():通常需要重写Thread类中的此方法,将创建的线程要执行的操作声明在此方法中
- 3.currentThread():静态方法,返回执行当前代码的线程
- 4.getName():获取当前线程的名字
- 5.setName():设置当前线程的名字
- 6.yield():释放当前CPU的执行权
- 7.join():在线程a中调用线程b的join()方法,此时线程a就进入阻塞状态,直到线程b完成执行完以后,线程a才结束阻塞状态
- 8.stop():已过时。当执行此方法时,强制结束当前线程
- 9.sleep(long millitime):让当前线程“睡眠”指定的millitime毫秒时间内,当前线程是最状态
- 10.isAlive():判断当前线程是否存活
线程的优先级:
- 1.定义在Thread类中的常量
MAX_PRIORITY:10
MIN_PRIORITY:1
NORM_PRIORITY:5 - 2.如何获取和设置当前线程的优先级:
getPriority():获取线程优先级
setPriority():设置线程优先级
说明:高优先级的线程抢占低优先级线程cpu的执行权。也只是概率问题,高优先级线程高概率被执行。
public class ThreadMethodTest {
public static void main(String[] args) {
//通过构造器给线程命名
HelloThread h1 = new HelloThread("Thread:1");
//通过内置setName()方法给线程命名
// h1.setName("线程一");
//设置分线程的优先级
h1.setPriority(Thread.MAX_PRIORITY);
h1.start();
//给主线程命名
Thread.currentThread().setName("主线程");
Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
for(int i = 0; i < 100; i ++) {
if (i % 2 != 0) {
System.out.println(Thread.currentThread().getName() + ":" + Thread.currentThread().getPriority() + ":" + i);
//Thread.currentThread().可以省略
}
// if (i == 20) {
// try {
// h1.join();
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
// }
}
// System.out.println(h1.isAlive());
}
}
class HelloThread extends Thread{
@Override
public void run() {
for(int i = 0; i < 100; i ++) {
if (i % 2 != 0) {
//父类中run方法没有抛异常,此处不能抛
// try {
// sleep(100);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
System.out.println(Thread.currentThread().getName() + ":" + Thread.currentThread().getPriority() + ":" + i);
}
//this只当前对象h1(可省略)
// if(i % 20 == 0){
// this.yield();
// }
}
}
public HelloThread(String name){
super(name);
}
}
练习:创建三个窗口买票,总票数为100张,使用继承Thread类的方式
- 存在安全问题,待解决
public class WindowTest {
public static void main(String[] args) {
Window w1 = new Window();
Window w2 = new Window();
Window w3 = new Window();
w1.setName("窗口1");
w2.setName("窗口2");
w3.setName("窗口3");
w1.start();
w2.start();
w3.start();
}
}
class Window extends Thread{
// private int ticket = 100;
private static int ticket = 100;//3个对象共享static变量
@Override
public void run() {
while (true){
if (ticket > 0){
System.out.println(Thread.currentThread().getName() + ":买票,票号为" + ticket);
ticket --;
}else {
break;
}
}
}
}
创建多线程的方式二:实现Runnable接口
-
1.创建一个实现了Runnable接口的类
-
2.实现类去实现Runnable中的抽象方法:run()
-
3.创建实现类的对象
-
4.将此对象作为参数传递到Thread类的构造器中,创建Thread类的对象
-
5.通过Thread类的对象调用start()
-
比较创建线程的两种方式
开发中:优先选择:实现Runnable接口的方式
原因:1.实现的方式没有类的单继承性的局限性
2.实现的方式更适合来处理多个线程有数据共享的情况
-
联系:public class Thread implements Runnable
-
相同点:两种方式都需要重写run(),将线程要执行的逻辑声明在run()中
//1.创建一个实现了Runnable接口的类
class MyThread_1 implements Runnable{
//2.实现类去实现Runnable中的抽象方法:run()
@Override
public void run() {
for(int i = 0; i < 100; i++){
if (i % 2 == 0){
System.out.println(Thread.currentThread().getName() + i);
}
}
}
}
public class ThreadTest1 {
public static void main(String[] args) {
//3.创建实现类的对象
MyThread_1 myThread_1 = new MyThread_1();
//4.将此对象作为参数传递到Thread类的构造器中,创建Thread类的对象
Thread t1 = new Thread(myThread_1);
t1.setName("线程一:");
//5.通过Thread类的对象调用start()①调用当前线程的run()-->调用Runnable类型的target
t1.start();
//再启动一个线程,遍历100以内的偶数
Thread t2 = new Thread(myThread_1);
t2.setName("线程二:");
t2.start();
}
}
练习:创建三个窗口买票,总票数为100张,使用实现Runnable接口的方式
class Window1 implements Runnable{
private int ticket = 100;
@Override
public void run() {
while (true){
if (ticket > 0) {
System.out.println(Thread.currentThread().getName() + "卖票,票号为:" + ticket);
ticket--;
} else {
break;
}
}
}
}
public class WindowTest1 {
public static void main(String[] args) {
Window1 w = new Window1();
//三个线程共用一个window对象,ticket不用设置static
Thread t1 = new Thread(w);
Thread t2 = new Thread(w);
Thread t3= new Thread(w);
t1.setName("窗口一");
t2.setName("窗口二");
t3.setName("窗口三");
t1.start();
t2.start();
t3.start();
}
}
关于线程生命周期中的几种状态转换