最近一直忙着看书,都没写点东西,不是因为懒,而是实在没什么好写的,最近在看:java多线程编程核心技术这本书,这本书确实是一本很好的多线程编程入门的书籍,即使是对于我这种很菜的人也能够读的明白。书看的不是很快,因为里面的代码自己都会认真的跟着敲一遍,然后理解其中的意思,总之还是挺不错的。接下来就来写一下近一周看书的感悟和收获。(书还没看完)
进程和多线程的概念:首先讲到进程,什么是进程?我们百度一下:
这个是百度给的解释:是程序关于某数据集合上的一次运动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。
同时这里也给出了关于线程的描述:进程是线程的容器。随着计算机的发展而演变出的线程,线程是更小的资源分配和调度的单位,是进程中独立运行的子任务。是因为进程过于庞大,而将进程分为好多子任务,这样进行资源的分配和调度就会执行的更快。(这是我对线程和进程之间关系的基本理解)
为什么使用多线程?假如两个任务:第一个任务需要十秒,第二个任务仅需要两秒,但是因为先来先服务的原则,第一个任务先执行,那么任务二就需要等任务一十秒后执行完毕后才能执行任务二。这个是单任务操作系统的执行任务的方法,效率非常的低,用户要等到十秒后才能执行任务二。但是如果是多任务操作系统,也就是任务进行多线程共同执行呢?任务一和任务二之间可以随意的切换,那么任务二就可以快速的完成,这样就提高了任务执行的效率。
然而我们java中怎么使用多线程编程嘞?实现多线程编程有两种途径:
①继承Thread类
②实现runnable接口
public class Thread implements Runnable
其实两种方式实现的效果都是一样的。
只是继承Thread类不支持多继承。
接线来给出继承Thread的例子:
package test;
public class ThreadA extends Thread {
public void run() {
System.out.println("多线程编程");
}
}
package test;
public class Run {
public static void main(String[] args) {
ThreadA a=new ThreadA();
a.start();
}
}
控制台输出:
多线程编程
继承Thread的类一定要实现run方法。
实现Runnable接口:
package test;
public class MyRunnable implements Runnable {
public void run() {
System.out.println("多线程编程");
}
}
package test;
public class Run {
public static void main(String[] args) {
Runnable myrunnable = new MyRunnable();
Thread a=new Thread(myrunnable);
a.start();
}
}
这里我们可以发现Thread构造函数可以传入Runnable接口的对象。
Thread(Runnable target) 这个是Thread的构造函数,所以构造函数里面也可以传入一个Thread对象。这样做的目的是:将一个线程的run方法交由其他线程调用,这里的例子就是讲mythread线程的run方法交由主线程调用。
接下来就是一些线程编程用到的一些常用的方法:
currentThread():返回当前线程
package getId;
public class test1 {
public static void main(String[] args) {
System.out.println(Thread.currentThread());
}
}
控制台输出:
Thread[main,5,main]
getName()和getId()方法:返回线程的name和id
package getId;
public class Test {
public static void main(String[] args) {
Thread runThread=Thread.currentThread();
System.out.println(runThread.getName()+" "+runThread.getId());
}
}
sleep(“毫秒数”)方法:让当前正在执行的线程暂停执行(休眠)
package Sleep;
public class MyThread1 extends Thread {
public void run() {
System.out.println("run threadName="+this.currentThread().getName()+"begin");
try {
Thread.sleep(2000);
System.out.println("run thread name="+this.currentThread().getName()+"end");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
package Sleep;
public class run1 {
public static void main(String[] args) {
MyThread1 thread=new MyThread1();
System.out.println("begin:"+System.currentTimeMillis());
thread.run();
System.out.println("end="+System.currentTimeMillis());
}
}
begin:1506772314142
run threadName=mainbegin//先跳出前边两项,过一会跳出后面两项。
run thread name=mainend
end=1506772316142
再看一段代码:
package Sleep;
public class MyThread2 extends Thread{
public void run() {
try {
System.out.println("run thread name:"+this.currentThread().getName()+"begin="+System.currentTimeMillis());
Thread.sleep(2000);
System.out.println("run threadName="+this.currentThread().getName()+"end="+System.currentTimeMillis());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
package Sleep;
public class run2 {
public static void main(String[] args) {
MyThread2 thread=new MyThread2();
System.out.println("begin="+System.currentTimeMillis());
thread.start();
System.out.println("end="+System.currentTimeMillis());
}
}
控制台输出:
begin=1506772556895
end=1506772556895
run thread name:Thread-0begin=1506772556895
run threadName=Thread-0end=1506772558895
有发现什么吗?
第二段代码是异步执行的。所以首先显示主线程的输出,然后显示Thread2输出。
要判断怎么判断一个线程是否是活动状态,我们使用isAlive()方法。
package isAlive;
public class MyThread extends Thread {
public void run() {
System.out.println("run="+MyThread.currentThread().isAlive());
}
}
package isAlive;
public class Run {
public static void main(String[] args) throws InterruptedException {
MyThread thread=new MyThread();
System.out.println("begin=="+thread.isAlive());
thread.start();
//Thread.sleep(1000);//添上睡眠
System.out.println("end=="+thread.isAlive());
}
}
控制台输出:
begin==false
end==true
run=true
将Run代码里的sleep注释去除将得到:
begin==false
run=true
end==false
就是因为thread已经执行完毕了,所以检测到thread不是活动状态。