面试都过了,就是技术分不够,郁闷了,现在分享我的学习笔记,以及一些电子书,赚点技术分。希望版主高抬贵手。
多线程概述:单线程如同一个餐厅只雇用一个服务员,服务员必须做完一件事情后才能做下一件事情。多线程如同一个餐厅雇佣很多名服务员,他们可以同时做很多事情,并且相互之间不会干扰。 一个程序被加载进内存运行时,就是一个进程,多线程使同一个进程可以并发处理多个任务,线程是进程的执行单元。一个进程可以拥有多个进程,一个线程必须有一个父进程。 每个线程拥有自己的堆栈,自己的程序计数器和自己的局部变量,但不拥有系统资源,多个线程共享父进程所拥有的全部资源。线程的执行时抢占式的,当前的线程在任何时候都可能被挂起,以便CUP运行另外的线程。 一个程序运行后至少有一个进程,一个进程可以包含多个程序,但至少包含一个线程。
线程的创建和启动:方法1:创建线程需要继承Thread类,并重写run(),run()代表线程需要完成的任务,run()是线程的执行体,启动线程通过start()。
- public class FirstThread extends Thread{
- private int i;
- @Override
- public void run(){
- for (; i < 100; i++) {
- System.out.println(this.getName()+"\t"+i);
- }
- }
- public static void main(String[] args) {
- for (int i = 0; i < 100; i++) {
- System.out.println(Thread.currentThread().getName()+" "+i);
- if(i==20){
- new FirstThread().start();
- new FirstThread().start();
- }
- }
- }
- }
复制代码在main()中当循环变量i=20时,启动两个线程。属性i在两个线程中的打印结果是不连续的,证明了多线程之间运行互不干扰,因为new了两个线程对象。以上程序启动时有3个线程,main()也是一个线程,成为主线程。 方法2:实现Runnable接口并实现run(),fun()方法内是线程的执行体。 - public class SecondThread implements Runnable {
- private int i;
- @Override
- public void run() {
- for (; i < 100; i++) {
- System.out.println(Thread.currentThread().getName() + "\t" + i);
- }
- }
- public static void main(String[] args) {
- SecondThread st = new SecondThread();
- for (int i = 0; i < 100; i++) {
- System.out.println(Thread.currentThread().getName()+" "+i);
- if(i==20){
- new Thread(st,"线程-1").start();
- new Thread(st,"线程-2").start();
- }
- }
- }
- }
复制代码通过实现Runnable接口在启动多线程时也需要使用Thread类并调用start()。这种方式创建的多个线程可以共享线程类中的属性,因为只创建一个Runnable接口的子类对象,这一个对象被Thread类引用。 方法3:通过实现Callable接口,并且实现call()。 - ublic class ThirdThread implements Callable<Integer> {
- @Override
- public Integer call() throws Exception {
- int i=0;
- for (; i <100; i++) { System.out.println(Thread.currentThread().getName()+"\t"+i);
- }
- return i;
- }
- public static void main(String[] args) throws Exception {
- ThirdThread tt = new ThirdThread();
- FutureTask<Integer> task = new FutureTask<Integer>(tt);
- for(int i=0;i<100;i++){
- System.out.println(Thread.currentThread().getName());
- if(i==20){
- new Thread(task,"有返回值的线程").start();
- }
- }
- System.out.println(task.get());
- }
- }
复制代码call()可以作为线程的执行体,call()比run()强大,可以有返回值,可以抛异常,Java5新增的接口。
线程的生命周期:
新建(New)à就绪(Runable)à运行(Running)à阻塞(Blocked)à死亡(Dead)
线程控制:join():调用线程将被阻塞,直到被join()加入的线程执行完为止。 - public class JoinThread extends Thread{
- public JoinThread(String name) {
- super(name);
- }
- @Override
- public void run(){
- for(int i=0;i<100;i++){
- System.out.println(this.getName()+"\t"+i);
- }
- }
- public static void main(String[] args) throws Exception {
- new JoinThread("新线程").start();
- for(int i=0;i<100;i++){
- if(i==20){
- JoinThread jt = new JoinThread("被Join的线程");
- jt.start();
- jt.join();
- }
- System.out.println(Thread.currentThread().getName()+"\t"+i);
- }
- }
- }
复制代码main线程调用了jt线程的join(),mian线程必须等jt线程执行结束后才会继续执行。 setDaemon():后台线程,如果所有前台线程都死亡,JVM会通知后台线程死亡,main线程默认是后台线程,设置一个线程为后台线程,必须在线程start()前设置。 - public class DaemonThread extends Thread {
- @Override
- public void run() {
- for (int i = 0; i < 1000; i++) {
- System.out.println(this.getName() + "\t" + i);
- }
- }
- public static void main(String[] args) {
- DaemonThread dt = new DaemonThread();
- dt.setDaemon(true);// 设置线程为后台线程
- dt.start();
- for (int i = 0; i < 10; i++) {
- System.out.println(Thread.currentThread().getName() + " " + i);
- }
- // 程序运行到此处,前台线程(main线程)结束,后台dt线程也随之结束
- }
- }
复制代码sleep():线程休眠,并进入阻塞状态。 - public class SleepThread {
- public static void main(String[] args) throws Exception {
- for (int i = 0; i < 10; i++) {
- System.out.println("Current time : "+new Date());
- Thread.sleep(1000);
- }
- }
- }
复制代码线程休眠后进入阻塞状态,并且不会获得CPU执行资格。 yield():让当前正在执行的线程暂停,但不会阻塞该线程,只是将线程转入就绪状态,暂停后只有优先级与当前线程相同,或者更高的处于就绪状态的线程财货获得CPU的执行资格。 - public class YieldTest extends Thread {
- private String name;
- public YieldTest(String name) {
- super(name);
- }
- @Override
- public void run() {
- for (int i = 0; i < 50; i++) {
- System.out.println(this.getName() + "\t" + i);
- if (i == 20)
- Thread.yield();
- }
- }
- public static void main(String[] args) {
- YieldTest y1 = new YieldTest("优先级高");
- y1.setPriority(Thread.MAX_PRIORITY);
- YieldTest y2 = new YieldTest("优先级低");
- y2.setPriority(Thread.MIN_PRIORITY);
- y1.start();
- y2.start();
- }
- }
复制代码
|