首先要制作QQ的话,一定要认识多线程,首先我们可以先从进程简单理解下。以下为个人简单理解,可能有误,我们知道系统有进程,但实际上只有一个CPU,一个时间内只能运行一个进程,例如只能运行QQ或者浏览器其中一个程序的进程,而造成我们认为他们并发进行的错觉是电脑更替进程的速度很快,以至于我们人眼上完全感觉不出来,所以就觉得个进程在运行,而线程就是属于某个进程的,一个进程里面可以有多个线程,然后线程也是在一个进程里面交替运行,但速度很快,以至于我们辨别不出,但它可以让一个程序的进程同时进行多种功能,例如运行中的QQ是一个进程,但它又会有多个线程,一个线程用于接收发来的信息,一个线程可以用来发送信息,一个线程可以用来检测QQ空间的信息等等,还有很多功能!
为什么要认识线程了,首先说C/S模式中的Server服务器,我们开启服务器了算一个进程,然后客户登录连接服务器的时候要为这个客户创建一个线程,用于处理有关他的信息等等,而Client客户端则需要多个线程要完成多个不同的任务,例如接收信息,发送信息,接收空间信息等等!
以上大概是一个 水的解释,严谨一点的话,可能会有错误,但原意应该不差。
下面为官方一点的解释:
进程和线程的区别:
进程:每个进程都有独立的代码和数据空间(进程上下文),进程间的切换会有较大的开销,一个进程包含1--n个线程。
线程:同一类线程共享代码和数据空间,每个线程有独立的运行栈和程序计数器(PC),线程切换开销小。
线程和进程一样分为五个阶段:创建、就绪、运行、阻塞、终止。
多进程是指操作系统能同时运行多个任务(程序)。
多线程是指在同一程序中有多个顺序流在执行。
在java中创建一个线程有两种方法,两者可以说是一样的,实现起来没有差别,只是一个是通过接口,一个是通过继承类
1、每个线程都必定有一个run方法,这是线程的主体;
2、每个线程都通过start方法来让线程进入就绪状态(就是线程可以开始运行了,但可能CPU正在执行其他进程或者线程,所以要等一下,就称为就绪,而不是运行,之后隔一段不定时间,CPU开始执行该线程,线程就开始运行了,就开始执行run方法里面的代码)。
3、当方法执行完run里面的代码后,这个线程就可以理解完结束了,就没有了。
①实现java.lang.Runnable接口,重写run()方法,启动:new Thread(this).start()。
package com.thread;
public class ThreadTest1 {
public static void main(String[] args) {
Runnable1 r = new Runnable1();
//r.run();并不是线程开启,而是简单的方法调用
Thread t = new Thread(r);//创建线程
//t.run(); //如果该线程是使用独立的 Runnable 运行对象构造的,则调用该 Runnable 对象的 run 方法;否则,该方法不执行任何操作并返回。
t.start(); //线程开启
for (int i = 0; i < 100; i++) {
System.out.println("main:"+i);
}
}
}
class Runnable1 implements Runnable{
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("Thread-----:"+i);
}
}
}//在这里要理解的是,这里有两个线程,一个是main方法的主线程,一个是t线程,因为两个线程会不定序运行,所以输出不一定相同
//这里程序的最后输出大概是0-99的输出,每个数都会有两次,由小到大,但有可能交换出现
//例如:0101223456347586一直下去,总之就可以理解为一个0-99的数列按小到大随意插入到另外一个0-99的数列中
②继承java.lang.Thread类,重写run()方法。实际上Thread就是实现了Runnable接口的类,所以可以说所有线程都是基于Runnable接口的。
要注意的是:
1.r.run()并不是启动线程,而是简单的方法调用。
2.Thread也有run()方法,如果该线程是使用独立的 Runnable 运行对象构造的,则调用该 Runnable 对象的 run 方法;否则,该方法不执行任何操作并返回。
3.并不是一启动线程(调用start()方法)就执行这个线程,而是进入就绪状态,什么时候运行要看CUP,里面有一个调度程序。
package com.thread;
public class TestThread2 {
public static void main(String[] args) {
Thread1 t = new Thread1();
//t.run(); //这里也不能直接调用方法
t.start();
for (int i = 0; i < 100; i++) {
System.out.println("main:"+i);
}
}
}
//尽量使用实现Runnnable接口,因为接口比较灵活
class Thread1 extends Thread{
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("Thread-----:"+i);
}
}
}
//这里程序的最后输出大概是0-99的输出,每个数都会有两次,由小到大,但有可能交换出现
//例如:0101223456347586一直下去,总之就可以理解为一个0-99的数列按小到大随意插入到另外一个0-99的数列中
有关线程的例子, 下面我们来一个简单一点的认识,到底多线程是怎么运行的!
package test;
public class TestThread2 {
public static void main(String[] args) {
Thread1 t1 = new Thread1(1);
Thread1 t2 = new Thread1(2);
t1.start();
t2.start();
}
}
// 尽量使用实现Runnnable接口,因为接口比较灵活
class Thread1 extends Thread {
int num;// 传递进来的参数num只是为了表明这是第几个线程
public Thread1(int num) {
this.num = num;
}
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("Thread" + num + ":" + i);
}
}
程序打印出来的结果其中一段:
当然了,这里线程的运行是随机的,所以运行的结果多种多样!
Thread2:3
Thread2:4
Thread2:5
Thread2:6
Thread2:7
Thread2:8
Thread2:9
Thread1:3
Thread2:10
Thread1:4
Thread2:11
大概线程的原理和创建就这样了!