Thread初探

文章目录

  1. 1. Thread初探
    1. 1.1. 前言
    2. 1.2. 创建线程
      1. 1.2.1. 继承Thread
      2. 1.2.2. 实现Runnable接口
      3. 1.2.3. 简便的创建方法
    3. 1.3. 常用的方法
      1. 1.3.1. 使用
      2. 1.3.2. 使用
      3. 1.3.3. 使用
      4. 1.3.4. 使用
    4. 1.4. 参考文章

Thread初探

前言

以前大家写的都是单线程的程序,全是在main函数中调用方法,可以清楚的看到它的效率是特别低的,就像python中使用单线程取爬一个网站,可以说能让你等的吐血,因为数据量实在太大了,今天我们就来看看java的并发编程多线程的学习

创建线程

创建一个线程可以有多种方法,比如继承Thread类,实现Runnable接口……下面我们来详细的看看创建的方法

继承Thread

为什么继承Thread可以直接调用start()方法启动线程呢,因为start()本身就是Thread的方法,也就是继承了Thread的start()方法,因此这个类的对象可以调用start()启动线程

//继承Thread
public class MyThread extends Thread {    
	public void run() {
		for (int i = 0; i < 10; i++) {
			System.out.println(this.getName()+"正在跑");
		}
	}
}

public class Test{
    public static void main(String[] args)
    {
        Mythread t1=new MyThread();   //创建对象
        t1.start();     //启动线程
    }
}

注意: 继承Thread类的创建方法一个对象只能创建一个线程,并不能多个线程共用一个对象,只能一个线程对应一个对象,因此我们来看看实现Runnable接口的类来实现多个线程共享同一个对象

实现Runnable接口

//实现Runnable接口
public class Demo implements Runnable {  
	@Override
	public void run() {
		for(int i=0;i<10;i++)
		{
			System.out.println(Thread.currentThread().getName()+"正在跑");
		}

	}
}

//测试类
public class Test{
    public static void main(String[] args)
    {
        Demo d=new Demo();  //创建对象
        Thread thread1=new Thread(d); //为对象创建一个线程
        Thread thread2=new Thread(d);   //创建另外一个线程
        
        //同时启动两个线程
        thread1.start();
        thread2.start();
    }
}

从上面可以清楚的看到实现Runnable接口的类一个对象可以供多个线程共享,并不像继承Thread类只为一个线程使用

简便的创建方法

直接在main方法中创建,如果创建的普通类的对象在外面,那么必须是final修饰,可以实现多个线程同时共享一个对象,这个和实现Runnable接口一样,这时候就要控制同步条件了,如果在run方法中定义对象,那么,就是一个线程对应一个对象,这个就和继承Thread类一样的效果。所以可以根据条件自由选择

//普通的一个类
public class Simple {

	public void display()
	{
		for(int i=0;i<10;i++)
		{
			System.out.println(Thread.currentThread().getName()+"正在跑");
		}
	}
}

//线程测试类
public class Test {
	public static void main(String[] args) {
    
    //如果在外面必须使用final,当然也可以直写在run方法中,不过写在外面可以实现多个线程共享一个对象
		//写在run方法中当前对象只能为一个线程使用,和继承Thread类一样的效果
		final Simple simple=new Simple(); 
		
		
		//下面创建使用同一个对象创建同两个线程,实现多个线程共享一个对象,和实现Runnable接口一样的效果
		Thread t1=new Thread(){
			public void run() {
				simple.display();
			};
		};
		
		Thread t2=new Thread(){
			public void run() {
				simple.display();
			};
		};
		
		//启动这两个线程
		t1.start();   
		t2.start();
    }}

常用的方法

  • static void sleep(long mils) 使正在运行的线程休眠mils毫秒,但是这里需要注意的是如果线程加了锁,那么使线程休眠并不会释放锁
  • String getName() 得到线程的名称,上面的程序中已经使用了这个方法
  • void setName(String name) 设置正在运行的线程的名字为name
  • start() 启动线程,线程的创建并不意味着线程的启动,只有调用start()方法线程才是真正的开始运行
  • long getId() 返回线程的标识符
  • run() 线程执行的代码都放在run()方法中,在run方法中的调用是有序的,都是按照程序运行的顺序开始执行

使用

下面使用上面的方法创建一个实例

//线程的类,继承Thread
public class MyThread1 extends Thread {

	public void run() { // 重载run方法,并且在其中写线程执行的代码块
		for (int i = 0; i < 10; i++) {
			// 获取线程的id和name
			System.out.println("Thread-Name:   " + this.getName()
					+ "   Thread-id:    " + this.getId());
			try {
				this.sleep(1000); // 线程休眠1秒
			} catch (InterruptedException e) {
				e.printStackTrace();
			}

		}

	}

}


//线程测试的类
public class Test {
	public static void main(String[] args) {
		MyThread1 t1 = new MyThread1(); // 创建线程
		t1.setName("第一个线程"); // 设置线程的名字

		MyThread1 t2 = new MyThread1();
		t2.setName("第二个线程");

		t1.start(); // 启动线程,开始运行
		t2.start();

	}
}

  • void join() 等待该线程终止才能运行其他的线程
  • void join(long mils) 等待该线程的时间为mils毫秒,一旦过了这个时间其他线程正常执行

使用

//线程类
public class MyThread1 extends Thread {

	public void run() { // 重载run方法,并且在其中写线程执行的代码块
		for (int i = 0; i < 10; i++) {
			// 获取线程的id和name
			System.out.println("Thread-Name:   " + this.getName()
					+ "   Thread-id:    " + this.getId());
			try {
				this.sleep(1000); // 线程休眠1秒
			} catch (InterruptedException e) {
				e.printStackTrace();
			}

		}

	}

}

//测试类
public class Test {
	public static void main(String[] args) {
		MyThread1 t1 = new MyThread1(); // 创建线程
		t1.setName("第一个线程"); // 设置线程的名字

		t1.start(); // 启动线程,开始运行
		try {
			t1.join();   //阻塞其他线程,只有当这个线程运行完之后才开始运行其他的线程
		} catch (InterruptedException e) {
			e.printStackTrace();
		}

		for (int i = 0; i < 10; i++) {
			System.out.println("主线程正在运行");
		}

	}
}


//输出结果

/*
Thread-Name:   第一个线程   Thread-id:    9
Thread-Name:   第一个线程   Thread-id:    9
Thread-Name:   第一个线程   Thread-id:    9
Thread-Name:   第一个线程   Thread-id:    9
Thread-Name:   第一个线程   Thread-id:    9
Thread-Name:   第一个线程   Thread-id:    9
Thread-Name:   第一个线程   Thread-id:    9
Thread-Name:   第一个线程   Thread-id:    9
Thread-Name:   第一个线程   Thread-id:    9
Thread-Name:   第一个线程   Thread-id:    9
主线程正在运行
主线程正在运行
主线程正在运行
主线程正在运行
主线程正在运行
主线程正在运行
主线程正在运行
主线程正在运行
主线程正在运行
主线程正在运行
 */

  • getPriority() 得到当前线程优先级
  • setPriority(int num) 更改线程的优先级(0-10)默认的是5,优先级越高获得cpu资源的几率就会越高

使用

//线程类
public class MyThread1 extends Thread {

	public void run() { // 重载run方法,并且在其中写线程执行的代码块
		for (int i = 0; i < 10; i++) {
			// 获取线程的id和name
			System.out.println("Thread-Name:   " + this.getName()
					+ "   Thread-id:    " + this.getId());
			try {
				this.sleep(1000); // 线程休眠1秒
			} catch (InterruptedException e) {
				e.printStackTrace();
			}

		}

	}

}


//测试类
public class Test {
	public static void main(String[] args) {
		MyThread1 t1 = new MyThread1(); // 创建线程
		t1.setName("第一个线程"); // 设置线程的名字

		MyThread1 t2 = new MyThread1();
		t2.setName("第二个线程");

		t2.setPriority(8);   //设置第二个线程的优先级为8,第一个线程的优先级为5(是默认的)

		t1.start();
		t2.start();

	}
}

/*
 * 从上面的运行结果可以看出大部分的第二个线程都是在第一个线程之前开始执行的,也就是说优先级越高获得cpu执行的几率就越大
 * /

  • setDaemon(boolean) 是否设置为守护线程,如果设置为守护线程,那么主线程销毁守护线程也会随之销毁
  • isDaemon() 判断是否为守护线程

使用

//测试类
public class MyThread1 extends Thread {

	public void run() { // 重载run方法,并且在其中写线程执行的代码块
		for (int i = 0; i < 10; i++) {
			// 获取线程的id和name
			System.out.println("Thread-Name:   " + this.getName()
					+ "   Thread-id:    " + this.getId());

			try {
				Thread.sleep(1000);  //休眠一秒,方便主线程运行结束
			} catch (InterruptedException e) {
				e.printStackTrace();
			}

		}

	}

}


public class Test {
	public static void main(String[] args) {
		MyThread1 t1 = new MyThread1(); // 创建线程
		t1.setName("第一个线程"); // 设置线程的名字
		t1.setDaemon(true);
		t1.start();

		for (int i = 0; i < 1; i++) {
			System.out.println(i);
		}

	}
}


//结果:
/*
 0
1
2
3
4
5
6
7
8
9
Thread-Name:   第一个线程   Thread-id:    9
*/


/*
 * 从上面的结果可以看出,一旦主线程结束,那么守护线程就会自动的结束
 * /

参考文章

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 并发编程之线程管理

    爱撒谎的男孩
  • Lock

    从上面的synchronized释放锁可以看出,只有synchronized代码块执行完毕或者异常才会释放,如果代码块中的程序因为IO原因阻塞了,那么线程...

    爱撒谎的男孩
  • 分布式锁-redis实现

    爱撒谎的男孩
  • 关于多线程,你必须知道的那些玩意儿

    进程和线程作为必知必会的知识,想来读者们也都是耳熟能详了,但真的是这样嘛?今天我们就来重新捋一捋,看看有没有什么知识点欠缺的。

    ClericYi
  • 深入理解多线程

    多线程是java中比较重要的一部分内容,使用多线程有许多的优点: - 提高应用程序的响应。对图形化界面更有意义,可增强用户体验。 - 程序需要实现一些需...

    栋先生
  • java高并发系列 - 第8天:线程组

    我们可以把线程归属到某个线程组中,线程组可以包含多个线程以及线程组,线程和线程组组成了父子关系,是个树形结构,如下图:

    路人甲Java
  • 【Android面试】关于多线程,你必须知道的那些玩意儿

    进程和线程作为必知必会的知识,想来读者们也都是耳熟能详了,但真的是这样嘛?今天我们就来重新捋一捋,看看有没有什么知识点欠缺的。

    Android技术干货分享
  • 关于多线程,你必须知道的那些玩意儿

    进程和线程作为必知必会的知识,想来读者们也都是耳熟能详了,但真的是这样嘛?今天我们就来重新捋一捋,看看有没有什么知识点欠缺的。

    字节流动
  • bat等大公司常考多线程面试题【力荐】

    思考题:希望大家积极的思考,并且可以踊跃的说出自己的想法,想法不管对与错,只要说出来就是一种提高,所以,希望小伙伴们可以把自己的想法在留言区给出,这样大家也可以...

    好好学java
  • 深读 JDK 源码丨Java Thread

    线程是系统资源分配的最小单位,它被包含在进程之中,是进程中的实际运作单位。JVM 允许应用程序同时运行、执行多个线程,每个线程都有优先权,具有较高优先级的线程优...

    码脑

扫码关注云+社区

领取腾讯云代金券