--------------------ASP.Net+Android+IOS开发、.Net培训、期待与您交流!
--------------------
1.进程
1.概述:
进程就是正在执行的一个程序。可以说是静态的,当进程一旦执行,那么就会在内存中给其分配一定的内存空间,供其运行。
2.从系统上来理解:进程有单进程和多进程
2-1.单进程:就是只能运行一个程序,只有这个程序运行完了,才能运行其他的进程,例如:DOS系统,他的特点就是只要是一种病毒,就会死机,原因就是采用的是单进程
2-2.多进程:就是可以同时运行多个程序,例如现在的Window系统,采用的就是多进程
2-3.Java虚拟机把其封装成了对象,供其使用。
2-4.进程和线程的之间的举例说明:打开qq程序,qq就是一个进程,那么线程就是其中的qq连天窗口。
2. 线程的概述
1.概述:线程是动态的,是进程中的控制单元,一个进程中可以执行多个线程,线程控制着进程。
2.一个进程中至少存在一个线程在执行,
例如:java虚拟机启动后,不只是存在的一个线程,一个是主线程,一个是垃圾回收的线程。
3.线程的执行必须是在有进程的基础之上,当一个线程消失了,那么进程不一定会消失,但是进程消失了,那么线程肯定会消失。
4.主线程:在系统中就是进程一旦创建,就是创建一个线程,那么就是个主线程,那么再有其他的线程生成的话,那就是其子类,在java虚拟机中的主线程是在运行主函数的线程。
5.多线程:多线程会提高执行速度(这只是多线程其中的一个功能例如:下载)当是多线程的话,那么各个线程之间会有优先级。当线程抢到了CPU,谁就会执行。
3. 线程的创建方法
3-1.继承Thread类。
1.定义类继承Thread类。
2.复写run()方法。
3.启动线程,使用start()方法
3-2.实现接口Runnable接口。
1.定义类(A)实现(implements)接口Runnable。
2.重写run()方法。
3.创建线程与类(A)创建联系,开启线程
4. 线程的创建---Thread类
4-1.代码举例
public class MyThread extends Thread { public void run(){ for(int i=0;i<10;i++) System.out.println(Thread.currentThread().getName()+"--"+i); } } 结果: main--0 Thread-0--0 main--1 Thread-0--1 main--2 Thread-0--2 Thread-0--3 main--3 Thread-0--4 main--4 Thread-0--5 main--5 Thread-0--6 main--6 Thread-0--7 main--7 Thread-0--8 main--8 Thread-0--9 main--9
从结果上可以看出,每次的运行结果都不一样,原因就是自定义的那个线程和主线程抢夺CPU,那一个先抢到CPU,那个就先执行。
4-2.start()和run()的区别和联系
联系:线程调用start()方法实际上是调用的run()方法,run()方法中存储的线程运行的代码
区别:调用start()方法是启动线程,直接调用run()方法的话,那么就和调用普通的方法是一样的,没有启动线程。
public class MyThread extends Thread { public void run(){ for(int i=0;i<10;i++) System.out.println(Thread.currentThread().getName()+"--"+i); } } public class Text { public static void main(String[] agrs) { MyThread tt = new MyThread(); tt.run(); for (int i = 0; i < 10; i++) System.out.println(Thread.currentThread().getName() + "--" + i); } }
这样的话,无论你运行多少次,那么结果都是一样的,因为就存在一个主线程,从结果你就可以看出的。
4-3.复写run()
run() 中存在的是线程运行的代码,对于主线程中运行的代码存储在main()方法中。
4-4.疑问解答
在主线程中,运行时候,也是按照顺序的。直到新的线程开启了,那么才会和存在线程抢夺CPU。
public class MyThread extends Thread { public void run(){ for(int i=0;i<10;i++) System.out.println(Thread.currentThread().getName()+"--"+i); } } public class Text { /* * 主线程开始从上向下执行,直到执行到了tt线程,启动了tt线程, * 但是此时主线程已经运行结束了,所以运行结果都是一样的。 * */ public static void main(String[] agrs) { for (int i = 0; i < 10; i++) System.out.println(Thread.currentThread().getName() + "--" + i); MyThread tt = new MyThread(); tt.start(); } } public class Text1{ /* * 主线程开始从上向下执行,开始就创建了线程,并且启动了tt线程, * 然后tt线程会和主线程抢夺CPU,谁抢到就会执行谁,所以此时运行结果是不确定的 * */ public static void main(String[] agrs) { MyThread tt = new MyThread(); tt.start(); for (int i = 0; i < 10; i++) System.out.println(Thread.currentThread().getName() + "--" + i); } }
5. 线程状态
6. 线程名称
6-1.默认的线程
默认线程的名称是Thread-0,Thread-2…….。主线程的名称是:main
public class Text { public static void main(String[] agrs) { MyThread tt = new MyThread(); System.out.println("默认的线程名称:"+tt.getName()); //tt.start(); System.out.println( "主线程的默认的名字:"+Thread.currentThread().getName()); } }
6-2.自定义线程
自定义线程名称和获得线程名称名
设置线程名称:可以用setName()方法,可以用构造方法设置线程名称
获得线程名称:用getName()方法获得线程名称
Thread.currentThread()获得当前运行的线程对象
public class MyThread extends Thread { public MyThread (String name){//通过构造方法设置线程名称 super(name); } public void run(){ } } public class Text { public static void main(String[] agrs) { MyThread tt = new MyThread("线程A"); System.out.println("线程名称:" + tt.getName()); // tt.start(); /* * 也可以通过setName()来设置线程名称 */ tt.setName("setName"); System.out.println("线程名称:" + tt.getName()); } } 结果: 线程名称:线程A 线程名称:setName
7. 售票小例子
public class Tick extends Thread { private int tick = 10; public void run() { while (tick > 0) { System.out.println(Thread.currentThread().getName() + "卖了第" + (tick--) + "张票"); } } } public class Text { public static void main(String[] agrs) { new Tick().start(); new Tick().start();//这样相当于开了3个线程,就是3个窗口 new Tick().start();//但是这样相当于各个窗口买各自的票,而不是共享票 } }
这样的结果相当于买了40张票,但是本来就10张票,重复卖了
结果:
Thread-0卖了第10张票
Thread-2卖了第10张票
Thread-1卖了第10张票
Thread-1卖了第9张票
Thread-2卖了第9张票
Thread-0卖了第9张票
解决办法
1. 把票(tick)定义成静态的,但是如果定义静态的话,但是静态变量声明周期长,不建议这样使用
public class Tick extends Thread { private static int tick = 10; public void run() { while (tick > 0) { System.out.println(Thread.currentThread().getName() + "卖了第" + (tick--) + "张票"); } } }
2.可以把值开启一个线程,结果没有错,但是和日常生活多个窗口共同卖票不符合
public class Text { public static void main(String[] agrs) { new Tick().start(); } }
3.使用实现Runnable接口线程处理此情况,最好了。具体的请查看 黑马程序员_<<线程(2)>>
--------------------ASP.Net+Android+IOS开发、.Net培训、期待与您交流!
--------------------