Java基础之多线程

0 . 什么是线程和进程?,请简要描述线程与进程的关系、区别及优缺点?

什么是进程?

进程是程序的一次执行过程。是系统中运行的一个任务。

是系统运行程序的基本单位。

操作系统资源管理的最小单位(包含资源的内存区域)。注: 线程不拥有资源管理。

什么是线程

线程只能归属于一个进程。并且只能访问该进程的资源。当前操作系统创建一个进程所拥有的资源。当操作系统创建以一个进程之后,会自动申请一个名为主线程或首要线程的线程。

linux中的进程 == 代码段 + 数据段 + 堆栈段 -----> 也就是程序+数据+进程控制块(Process Control Block)

PCB

PCB包括创建进程、执行程序、退出进程以及改变进程的优先级等等。而进程中的PCB用一个名为task_struct的结构体来表示。

什么是多线程

多线程就是多个线程同时或者交替运行。单核CPU是顺序执行,也就是交替运行。

线程使用场合?

  • 在一个程序中需要同时完成多个任务。-----> 将每一个任务定义为一个线程,使得一同工作。

  • 在单线程中可以完成,但是多线程下载更快。例如,多线程突破下载限制。

并发并行

OS将时间划分成若干时间片段。尽可能均匀的分配给各线程。以时间片段为时间单位交替执行。

并发: 偏重于多个任务交替执行。多个任务仍有可能串行。

并行: “同时执行”

同步和异步

同步: 实时处理,就是在发出一个功能调用时,在没有得到结果之前,该调用就不返回。普通B/S模式。

  • 浏览器向服务器提交请求—> 等待服务器响应/处理 -->处理后返回结果----> 处理完毕(这个期间客户端浏览器不能做任何事)

异步:分时处理,当一个异步过程调用发出后,调用者不能立刻得到结果。实际处理这个调用的部件在完成后,通过状态、通知和回调来通知调用者。不一定马上处理,等候区。Ajax技术(异步)

  • 请求事件触发 —> 等待服务器处理(浏览器仍可以做其他事) —> 处理完毕

1. 多线程实现方式

继承Thread类

class MyThread extends Thread {
	@Override
	public void run() {
        for(int i=0;i<1000;i++)
			System.out.println(this.getName());
	}
}
class Run{
    public static void main(String[] args) {
		new MyThread().start();
		new MyThread().start();
		System.out.println("运行结束");
	}
}

实现Runnable接口

public class MyRunnable implements Runnable {
	@Override
	public void run() {
		for(int i=0;i<1000;i++)
			System.out.println(this.getName());
	}
}
class Run{
    public static void main(String[] args) {
		new Thread(new MyRunnable()).start();
		new Thread().start(new MyRunnable());
		System.out.println("运行结束");
	}
}

使用线程池

// TODO

2. 线程状态

2.1 如何停止一个线程

interrupted()

public class InterruptThread2 extends Thread {
	@Override
	public void run() {
		super.run();
		for (int i = 0; i < 500000; i++) {
			if (this.interrupted()) {
				System.out.println("已经是停止状态了!我要退出了!");
				break;
			}
			System.out.println("i=" + (i + 1));
		}
		System.out.println("看到这句话说明线程并未终止------");
	}

	public static void main(String[] args) {
		try {
			InterruptThread2 thread = new InterruptThread2();
			thread.start();
			Thread.sleep(2000);
			thread.interrupt();
		} catch (InterruptedException e) {
			System.out.println("main catch");
			e.printStackTrace();
		}
	}
}

return

public class MyThread extends Thread {

	@Override
	public void run() {
			while (true) {
				if (this.isInterrupted()) {
					System.out.println("ֹͣ停止了!");
					return;
				}
				System.out.println("timer=" + System.currentTimeMillis());
			}
	}
	public static void main(String[] args) throws InterruptedException {
		MyThread t=new MyThread();
		t.start();
		Thread.sleep(2000);
		t.interrupt();
	}

}

2.2 /TODO/

3. 线程的API

static Thread currentThread()

返回对当前正在执行的线程对象的引用。

long getId()

返回此线程的唯一标识符。

final int getPriority()

返回线程优先级.

线程优先级

​ 线程启动后就纳入到线程调度器中统一管理。线程只能被动的被分配给时间片来并发执行。至于何时获取时间片,以及时间片分配给哪个线程由 ”线程调度器 “ 来决定。

​ 线程调度器分配时间片并非每个线程绝对均匀分配。但是概率一致。

​ 修改线程的优先级可以最大成都的干涉线程调度器分配时间片的概率。理论上: 优先级越高的线程获取时间片的次数越多。

boolean isAlive

是否还处于活动状态(正在运行/准备运行阶段)

static native void sleep(long millis) throws InterruptException

当前线程*“休眠”*指定时长。使当前正在执行的线程休眠(暂时停止执行)指定的毫秒数。取决于主体(主体)定时器和调度程序的精度和准确性。 <!–线程不会失去任何监视器的所有权。->

String toString()

如果有groupName,则返回 name,priority,thread group; 否则 无group.

interrupted() & isInterrupted()

interrupted(): 测试当前线程是否已经是中断状态。执行后将状态标志清除为false的功能。

isInterrupted():测试线程Thread对相关是否已经是中断状态。

 		/**
		  * 在eclipse jdk版本为javaSE-1.8时不需要写final
		  * 有版本问题
		  */
		/*final*/ Thread lin  = new Thread(){
			@Override
			public void run() {
				System.out.println("lin: 刚美容,睡会吧.");
				try {
					Thread.sleep(100000);
				} catch (InterruptedException e) {
					System.out.println("lin: 干嘛呢???干嘛呢??!!!!!!!");
				}
				System.out.println("lin: 醒了!!?");
			}
		};
		
		Thread huang = new Thread(){
			
			@Override 
			public void run() {
				System.out.println("huang: 开始砸墙!!!");
				for (int i = 0; i < 5; i++) {
					System.out.println("huang: 80!");
					try {
						Thread.sleep(1000);
					} catch (InterruptedException e) {
					}
				}
				System.out.println("huang: 搞定!!");
                /**
                 * 当进程处于sleep状态时,可以通过interrupt中断该异常。
                 */
				lin.interrupt();
			}
		};
		lin.start();
		huang.start();

yield()

yield()方法的作用是放弃当前的CPU资源,将它让给其他的任务去占用CPU时间。注意:放弃的时间不确定,可能一会就会重新获得CPU时间片。

setPriority(int newPriority)

更改此线程的优先级。(1~10权重递增)

优先级可以表明在程序中,该线程优先获得被调度机会的权重。但所有线程理论上被调度的可能性时一样的(所以也就意味着不代表高优先级的线程一定是先执行。)。

  • 线程优先级具有继承特性比如A线程启动B线程,则B线程的优先级和A是一样的。
  • 线程优先级具有随机性也就是说线程优先级高的不一定每一次都先执行完。

join()

等待该线程终止。当a线程生成了b线程。b线程独立做逻辑处理,但是a线程需要b线程的结果(也就是说,a线程需要等b线程执行完的处理结果)。这时候就需要join()方法。

setDaemon(true)

  1. setDaemon(true)必须在start()方法前执行,否则会抛出IllegalThreadStateException异常
  2. 在守护线程中产生的新线程也是守护线程
  3. 不是所有的任务都可以分配给守护线程来执行,比如读写操作或者计算逻辑
class MyThread extends Thread {
	private int i = 0;

	@Override
	public void run() {
		try {
			while (true) {
				i++;
				System.out.println("i=" + (i));
				Thread.sleep(100);
			}
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}
public class Run {
	public static void main(String[] args) {
		try {
			MyThread thread = new MyThread();
			thread.setDaemon(true);
			thread.start();
			Thread.sleep(5000);
			System.out.println("我离开thread对象也不再打印了,也就是停止了!");
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

参考

多线程相关

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值