1、进程和线程的区别
1、进程:进程是程序的一次动态执行过程,它需要经历从代码加载,代码执行到执行完毕的一个完整过程,这个过程也是进程本身从产生,发展到最后消亡的过程,一个进程可能由多个线程组成
多线程是实现并发机制的一种有效手段。进程和线程一样,都是实现并发的一个基本单位
2、线程:线程是比进程更小的执行单位,线程是在进程的基础上进行进一步的划分。所谓多进程是指一个进程在执性过程中可以产生多个更小的程序单元,这些更小的单元称为线程,这些线程可以同时存在,同时运行。一个进程中可能包含了很多同时执行的线程。
多线程机制指可以同时运行多个程序块,使程序运行效率变得很高,可以克服传统程序语言所无法解决的问题。例如,有些包含循环的线程可能要使用一段时间来运算,此时便可让另一个线程来做其他的处理。
2、java中实现多线程操作的方法
1、继承Thread类。
2、实现Runnable接口。
如果要正确的启动线程,是不能直接调用run()方法的,而是应该调用从Thread类中继承而来的start()方法。具体代码如下
class MyThread extends Thread{
private String name;
public MyThread(String name) {
this.name=name;
}
public void run() {
for(int i=1;i<=5;i++) {
System.out.println(name+"运行"+i);
}
}
}
public class Lianxi0312 {
public static void main(String[] args) {
MyThread t1 = new MyThread("线程A:");
MyThread t2 = new MyThread("线程B:");
t1.start();
t2.start();
}
}
运行结果:
线程A:运行1 线程B:运行1 线程A:运行2 线程B:运行2 线程A:运行3 线程B:运行3 线程B:运行4 线程B:运行5 线程A:运行4 线程A:运行5
*如果要通过继承Thread类实现多线程,则必须覆写run()方法。
3、线程的状态:
4、线程操作的相关方法
1、取得和设置线程的名称
用getName()方法取得线程的名称。用setName()方法设置线程的名称。
如果没有设置名称,系统会为其自动分配名称。名称的格式为Thread-Xx。
观察下面一段代码:
class MyThread implements Runnable{
private String name;
public void run() {
for(int i=1;i<=5;i++) {
System.out.println(Thread.currentThread().getName()+"运行"+i);
//取得当前线程的名称
}
}
}
public class Lianxi0312 {
public static void main(String[] args) {
MyThread t1 = new MyThread();
new Thread(t1,"线程").start();
t1.run();
}
}
运行结果:
main运行1
线程运行1
main运行2
线程运行2
main运行3
线程运行3
main运行4
线程运行4
线程运行5
main运行5
取得当前线程名字的代码为:Thread.currentThread().getName()
主方法实际上也是一个线程。
java中所有的线程都是同时启动的,哪个线程先抢占到了CPU资源,哪个线程就先运行。
一个java程序运行是至少会启动两个线程。
2、判断线程是否启动
在java中可以使用isAlive()这个方法来测试线程是否已经启动而且仍在运行。
使用格式为 Thread的实例化对象
对象.isAlive()
如果启动或存活返回true,否则返回false。
代码如下:
主线程有可能比其他线程先执行完,但是不会影响其他线程,其他线程不会因为主线程的结束而结束。
3、线程的强制运行
可以使用一个join()方法让一个线程强制运行。
例:
格式:对象.join(),不过要加入异常处理。
4、线程的休眠
使用Thread.sleep()方法。
括号里是休眠的时间,以毫秒为单位。
也要加入异常处理try, catch
catch的方法体不做任何处理。
5、中断线程
直接通过interrupt()方法中断其运行状态。
使用方法:对象.interrupt();
6、后台线程
直接使用setDaemon()方法即可
使用方法:对象.方法(true/false)
7、线程的优先级
主方法的优先级是NORM_PRIORITY。
8、线程的礼让
用yield()方法将一个线程的操作暂时让给其他线程执行。
使用方法:Thread.currentThread().yield();
5、同步与死锁
本章要点
第一题:
class Data {
private int j=0;
public synchronized void add(){
System.out.println(Thread.currentThread().getName()+"对j加1,当前="+(++j));
}
public synchronized void dec(){
System.out.println(Thread.currentThread().getName()+"对j减1,当前="+(--j));
}
}
class Add implements Runnable{
private Data data;
Add(Data data){
this.data=data;
}
public void run(){
data.add();
}
}
class Dec implements Runnable{
private Data data;
Dec(Data data){
this.data=data;
}
public void run(){
data.dec();
}
}
public class Test1 {
public static void main(String[] args) {
// TODO 自动生成的方法存根
Data data = new Data();
Add add = new Add(data);
Dec dec = new Dec(data);
for(int i = 0;i<2;++i){
new Thread(add,"线程A").start();
new Thread(dec,"线程B").start();
}
}
}
运行结果:
线程A对j加1,当前=1
线程A对j加1,当前=2
线程B对j减1,当前=1
线程B对j减1,当前=0
第二题:
public class Computer {
private String name;
private static int sum=1;
private boolean flag=true;
public Computer(String name){
this.name=name;
}
public synchronized void set(){
if(!flag){
try{
super.wait();
}catch(InterruptedException e){
e.printStackTrace();
}
}
try{
Thread.sleep(1000);
}catch(InterruptedException e){
e.printStackTrace();
}
System.out.println("生产了"+this.name+",现在已经生产了"+sum+"台电脑");
sum++;
flag=false;
super.notify();
}
public synchronized void get(){
if(flag){
try{
super.wait();
}catch(InterruptedException e){
e.printStackTrace();
}
}
try{
Thread.sleep(1000);
}catch(InterruptedException e){
e.printStackTrace();
}
System.out.println("搬走了"+this.name+"");
flag=true;
super.notify();
}
}
public class Test2 {
public static void main(String[] args) {
// TODO 自动生成的方法存根
ThreadCom t1=new ThreadCom();
new Thread(t1).start();
}
}
class ThreadCom implements Runnable{
public void run(){
for(int i=0;i<10;i++){
Computer c=new Computer("电脑"+i);
c.set();
c.get();
}
}
}
运行结果:
生产了电脑0,现在已经生产了1台电脑
搬走了电脑0
生产了电脑1,现在已经生产了2台电脑
搬走了电脑1
生产了电脑2,现在已经生产了3台电脑
搬走了电脑2
生产了电脑3,现在已经生产了4台电脑
搬走了电脑3
生产了电脑4,现在已经生产了5台电脑
搬走了电脑4
生产了电脑5,现在已经生产了6台电脑
搬走了电脑5
生产了电脑6,现在已经生产了7台电脑
搬走了电脑6
生产了电脑7,现在已经生产了8台电脑
搬走了电脑7
生产了电脑8,现在已经生产了9台电脑
搬走了电脑8
生产了电脑9,现在已经生产了10台电脑
搬走了电脑9
notify():
唤醒在此对象监视器上等待的单个线程。如果所有线程都在此对象上等待,则会选择唤醒其中一个线程。选择是任意性的,并在对实现做出决定时发生。线程通过调用其中一个 wait 方法,在对象的监视器上等待。
直到当前线程放弃此对象上的锁定,才能继续执行被唤醒的线程。被唤醒的线程将以常规方式与在该对象上主动同步的其他所有线程进行竞争;例如,唤醒的线程在作为锁定此对象的下一个线程方面没有可靠的特权或劣势。