
程序:静态的代码,安装到硬盘上
进程:运行中的程序,是操作系统分配资源的最小单位
线程:线程是进程(程序)中最小的执行单元,是操作系统进行任务调度的最小单位是CPU进行调度的最小单位.
一个进程可以包含多个线程,一个线程只能属于一个进程,线程不能脱离进程而独立运行
每一个进程至少包含一个线程(称为主线程);在主线程中开始执行程序, java 程序的入口main()方法就是在主线程中被执行的.
在主线程中可以创建并启动其它的线程;
一个进程内的所有线程共享该进程的内存资源。
以QQ聊天为例,登录QQ后我们可以打开多个聊天窗口,同时和张三、李四、王五...聊天. 登录QQ就是通过主线程启动了QQ这个进程,相当于进入main()方法.而我们打开多个聊天窗口相当于创建了多个线程,这些线程都隶属于QQ这个进程.如图:
一个简单的线程创建包:com.ffyc.javathread包
创建类:Sample类
package com.ffyc.javathread;
public class Sample {
//方法1
public void method1(){
System.out.println("method1");
}
//方法2
public void method2(){
method1();
System.out.println("method2");
}
public static void main(String[] args) {
System.out.println("主线程开始");
Sample s = new Sample();
s.method2();
System.out.println("主线程结束");
}
}
这是一个单线程的典例,输出的结果为:
主线程开始
method1
method2
主线程结束
在类中,从main()方法进入程序,首先打印输出:"主线程开始";然后创建了Sample这个类的对象,调用该类里的方法:method2()-->进入该方法,method2()方法调用了方法:method1()-->进入该方法,执行method1()的方法体:打印输出"method1",执行完method1()后,返回method2()中继续向后执行,打印输出:"method2",执行完method2()方法体后返回到主方法,执行面的语句,输出:"主线程结束".如图:
调用的过程可以用下图表示:
显然,整个程序是顺着一条线完成的,这是一个典型的单线程.
创建线程创建线程有两种方式,我们依次介绍:
继承Thread类的方式
实现Runnable接口的方式
一、继承Thread类的方式
在Java中要实现线程,最简单的方式就是扩展Thread类,重写其中的run方法,方法原型如下:
Thread类中的run方法本身并不执行任何操作,如果我们重写了run方法,当线程启动时,它将执行 run方法。
main()方法也是一个线程,还是启动程序的主线程,所以下面的main()方法中,start()方法启动ThreadDemo线程后,就有两个线程.这两个线程的运行没有固定的先后顺序,由操作系统的调度决定.
创建包:com.ffyc.javathread.demo1
创建类:test
创建类:ThreadDemo
package com.ffyc.javathread.demo1;
//ThreadDemo类
public class ThreadDemo extends Thread{
@Override
public void run() {
for (int i = 0; i < 1000; i++) {
System.out.println("ThreadDemo"+i);
}
}
}
//Test测试类
public class Test {
public static void main(String[] args) {
ThreadDemo td = new ThreadDemo(); //创建线程
td.start();
for (int i = 0; i < 1000; i++) {
System.out.println("main"+i);
}
}
}
.***run()方法重写的内容就是线程启动后要执行的内容.main()方法执行时:
创建了一个ThreadDemo对象,此时是创建了一个线程(ThreadDemo这个类继承(extends)了Thread类,重写了run()方法)
调用Start()方法启动线程
此时main()方法的主线程和刚启动的另一个线程由CPU调度执行,没有固定的先执行哪个,后执行哪个
main线程要执行的是:
for (int i = 0; i < 1000; i++) {
System.out.println("main"+i);
}
td线程要执行的是run()方法中的:
for (int i = 0; i < 1000; i++) {
System.out.println("ThreadDemo"+i);
}
他们交替执行的结果可以自己运行看一下.
二、实现Runnable接口的方式
1. java.lang.Runnable接口中仅仅只有一个抽象方法:
public void run();
2. 也可以通过实现Runnable接口的方式来实现线程,只需要实现其中的run方法即可;
3. Runnable接口的存在主要是为了解决Java中不允许多继承的问题
如果使用继承(extends)Thread类的方式实现创建一个进程,那么这个类将不能再继承其他的类,但是如果是实现接口,那么可以实现多个接口,且不影响继承想继承的类.
***实现runnable接口的方法:
public class MyThread implements runnable{
@Override
public void run(){
方法体;
}
}
***创建接口的关键语句:
MyThread r = new MyThread(); //创建一个对象 Thread thread = new Thread(r); thread.start();
二、举个例子
创建包:package com.ffyc.javathread.demo2
创建类:Test类
创建类:MyThread类
package com.ffyc.javathread.demo2;
public class MyThread implements Runnable {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+Thread.currentThread().getPriority());
}
}
package com.ffyc.javathread.demo2;
public class Test {
public static void main(String[] args) {
MyThread myth = new MyThread();//创建对象
Thread th = new Thread(myth,"窗口1");
//创建了一线程,并为这个线程分配了一个任务,创建线程名称:"窗口1"
th.start();//启动线程
Thread th2 = new Thread(myth); //创建第二个线程
th2.setName("窗口2"); //用setName()方法为线程命名:"窗口2"
th2.start(); //启动线程th2
Thread.currentThread().setPriority(10);获取当前线程,并给它设置优先级:10
th.setPriority(8);//给th线程设置优先级 8
th2.setPriority(6);//给th2设置优先级 6
System.out.println("main"+Thread.currentThread().getPriority());
//输出main方法(主线程)的优先级
}
}
上面的部分main()方法中有3个线程:main()方法的主线程,th线程和th2线程.三者的先后顺序也是有CPU的调度决定的.
线程的常用类1. 构造方法; //构造方法之间的调用 用的是this(所调用的构造方法的参数列表) 2. run(); 用于线程执行的任务 3. start(); 用于启动线程 4. Thread.currentThread() 用于获得当前线程的引用 5. getName(); 获得线程的名字 7. setName();给线程命名
常用类请大家自己尝试使用~